web-dev-qa-db-fra.com

NSCalendar premier jour de la semaine

Est-ce que quelqu'un sait s'il existe un moyen de définir le premier jour de la semaine sur un calendrier NSC, ou existe-t-il un calendrier qui a déjà le lundi comme premier jour de la semaine, au lieu de dimanche… .. Je travaille actuellement sur une application basée sur une semaine de travail et devant commencer le lundi et non le dimanche. Je peux très probablement travailler avec cela, mais il y aura beaucoup de cas critiques. Je préférerais que la plateforme le fasse pour moi.

Merci d'avance

Voici quelques-uns du code que j'utilise. J'espère que le jour de la semaine serait 6 au lieu de 7, ce qui voudrait dire que dimanche serait 7 au lieu de passer à 0.

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setFirstWeekday:0];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit | NSWeekCalendarUnit | NSWeekdayCalendarUnit;
NSDateComponents *todaysDate = [gregorian components:unitFlags fromDate:[NSDate date]];
int dayOfWeek = todaysDate.weekday;
42
Joshua

Edit: Ceci ne vérifie pas le cas Edge où le début de la semaine commence le mois précédent. Un code mis à jour pour couvrir ceci: https://stackoverflow.com/a/14688780/308315


Si vous faites toujours attention à cela, vous devez utiliser 

ordinalityOfUnit:inUnit:forDate:

et définissez firstWeekday sur 2. (1 == dimanche et 7 == samedi)

Voici le code:

NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[gregorian setFirstWeekday:2]; // Sunday == 1, Saturday == 7
NSUInteger adjustedWeekdayOrdinal = [gregorian ordinalityOfUnit:NSWeekdayCalendarUnit inUnit:NSWeekCalendarUnit forDate:[NSDate date]];
NSLog(@"Adjusted weekday ordinal: %d", adjustedWeekdayOrdinal);

Rappelez-vous que les ordinaux des jours de la semaine commencent à 1 pour le premier jour de la semaine et non à zéro.

Lien vers la documentation .

77
Kris Markel

Ce code construit une date définie sur le lundi de la semaine en cours:

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDate *today = [NSDate date];
NSDate *beginningOfWeek = nil;
BOOL ok = [gregorian rangeOfUnit:NSWeekCalendarUnit startDate:&beginningOfWeek
                                interval:NULL forDate: today];

setFirstWeekday: sur l'objet NSCalendar ..__ Définit l'index du premier jour de la semaine pour le destinataire.

- (void)setFirstWeekday:(NSUInteger)weekday

Devrait faire l'affaire.

12
mmc

À mon avis, ces paramètres doivent être dynamiques en fonction des paramètres régionaux de l'utilisateur . Par conséquent, il convient d'utiliser:

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setLocale:[NSLocale currentLocale]];

Le calendrier sera ainsi automatiquement défini le premier jour de la semaine en fonction des paramètres régionaux de l'utilisateur. Sauf si vous développez votre application pour un objectif spécifique/des paramètres régionaux (ou préférez permettre à l'utilisateur de choisir ce jour).

10
Amir Naor

J'ai eu du mal avec beaucoup de réponses ici. . c'était peut-être juste moi. . 

Voici une réponse qui fonctionne pour moi:

- (NSDate*)firstDayOfWeek
{
    NSCalendar* cal = [[NSCalendar currentCalendar] copy];
    [cal setFirstWeekday:2]; //Override locale to make week start on Monday
    NSDate* startOfTheWeek;
    NSTimeInterval interval;
    [cal rangeOfUnit:NSWeekCalendarUnit startDate:&startOfTheWeek interval:&interval forDate:self];
    return startOfTheWeek;
}

- (NSDate*)lastDayOfWeek
{
    NSCalendar* cal = [[NSCalendar currentCalendar] copy];
    [cal setFirstWeekday:2]; //Override locale to make week start on Monday
    NSDate* startOfTheWeek;
    NSTimeInterval interval;
    [cal rangeOfUnit:NSWeekCalendarUnit startDate:&startOfTheWeek interval:&interval forDate:self];
    return [startOfTheWeek dateByAddingTimeInterval:interval - 1];
}

Mettre à jour:

Comme indiqué ( ailleurs ) par @vikingosegundo, il est généralement préférable de laisser la section locale déterminer le jour du début de la semaine. Toutefois, dans ce cas, l'OP demandait que le début de la semaine ait lieu lundi Par conséquent, nous copions le calendrier système et remplaçons le firstWeekDay. 

8
Jasper Blues

Le problème avec la réponse de Kris est le cas Edge où le début de la semaine commence le mois précédent. Voici un code plus simple qui vérifie également le cas Edge:

// Finds the date for the first day of the week
- (NSDate *)getFirstDayOfTheWeekFromDate:(NSDate *)givenDate
{
    NSCalendar *calendar = [NSCalendar currentCalendar];

    // Edge case where beginning of week starts in the prior month
    NSDateComponents *edgeCase = [[NSDateComponents alloc] init];
    [edgeCase setMonth:2];
    [edgeCase setDay:1];
    [edgeCase setYear:2013];
    NSDate *edgeCaseDate = [calendar dateFromComponents:edgeCase];

    NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:edgeCaseDate];
    [components setWeekday:1]; // 1 == Sunday, 7 == Saturday
    [components setWeek:[components week]];

    NSLog(@"Edge case date is %@ and beginning of that week is %@", edgeCaseDate , [calendar dateFromComponents:components]);

    // Find Sunday for the given date
    components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:givenDate];
    [components setWeekday:1]; // 1 == Sunday, 7 == Saturday
    [components setWeek:[components week]];

    NSLog(@"Original date is %@ and beginning of week is %@", givenDate , [calendar dateFromComponents:components]);

    return [calendar dateFromComponents:components];
}
7
iwasrobbed

Je l'ai fait comme ça.

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *today = [NSDate date];
NSDateComponents *compForWeekday = [gregorian components:(NSWeekdayCalendarUnit) fromDate:today];
NSInteger weekDayAsNumber = [compForWeekday weekday]; // The week day as number but with sunday starting as 1

weekDayAsNumber = ((weekDayAsNumber + 5) % 7) + 1; // Transforming so that monday = 1 and sunday = 7

Je vois un malentendu dans les autres messages. Le premier jour de la semaine, quel qu’il soit, porte le numéro 1 et non 0. Par défaut, dimanche = 1, comme indiqué dans "Introduction au Guide de programmation de la date et de l’heure pour Cocoa: calculs calendaires":

"La valeur du jour de la semaine du dimanche dans le calendrier grégorien est 1"

Pour le lundi comme premier jour ouvrable, le seul remède dont je dispose est la condition de force brute pour effectuer le calcul

NSCalendar *cal=[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [cal components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
// set to 7 if it's Sunday otherwise decrease weekday number
NSInteger weekday=[comps weekday]==1?7:[comps weekday]-1; 
3
ciukes

Ci-dessous couvre également le cas Edge,

- (NSDate *)getFirstDayOfTheWeekFromDate:(NSDate *)givenDate
{
    NSCalendar *calendar = [NSCalendar currentCalendar];


   NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:givenDate];
    [components setWeekday:2]; // 1 == Sunday, 7 == Saturday
    if([[calendar dateFromComponents:components] compare: curDate] == NSOrderedDescending) // if start is later in time than end
    {
        [components setWeek:[components week]-1];
    }

    return [calendar dateFromComponents:components];
}
1
Sarim Sidd

Mon moyen simple de faire cela est d’obtenir lundi = 0, dimanche = 6:

    NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
    NSInteger dayNumStartingFromMonday = ([dateComponents weekday] - 2 + 7) % 7;    //normal: Sunday is 1, Monday is 2
0
CharlesA

Essaye ça: 

NSCalendar *yourCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
[yourCal setFirstWeekday:0];
0
nicktmro

Le calendrier ISO 8601 semble avoir son premier jour de la semaine défini sur lundi par défaut.

0
Christian Schnorr

Vous pouvez simplement changer .firstWeekday du calendrier.

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
calendar.firstWeekday = 2;

Ensuite, utilisez rangeOfUnit:startDate:interval:forDate: pour obtenir le premier jour

NSDate *startOfWeek;
[calendar rangeOfUnit:NSCalendarUnitWeekOfYear startDate:&startOfWeek interval:nil forDate:[NSdate date]];
0
trapper

Utilisation du calendrier nextWeekend (iOS 10 ou version ultérieure) et ordinality (merci @ kris-markel) J'ai eu lundi comme premier de la semaine pour le calendrier en_US.

En voici un exemple avec le repli sur firstWeekday:

extension Calendar {
    var firstWorkWeekday: Int {
        guard #available(iOS 10.0, *) else{
            return self.firstWeekday
        }
        guard let endOfWeekend = self.nextWeekend(startingAfter: Date())?.end else {
            return self.firstWeekday
        }
        return self.ordinality(of: .weekday, in: .weekOfYear, for: endOfWeekend) ?? self.firstWeekday
    }
}
0
ugiflezet