iphone cocoa calendar weekday nscalendar

iphone - NSCalendar primer día de la semana



cocoa weekday (16)

¿Alguien sabe si hay una manera de establecer el primer día de la semana en un NSCalendar, o hay un calendario que ya tiene el lunes como el primer día de la semana, en lugar del domingo. Actualmente estoy trabajando en una aplicación que se basa en una semana de trabajo, y debe comenzar el lunes, no el domingo. Es muy probable que pueda trabajar para solucionar este problema, pero habrá muchos casos de esquina. Prefiero que la plataforma lo haga por mí.

Gracias por adelantado

Aquí hay un poco del código que estoy usando. es sábado ahora, entonces lo que espero es que el día de la semana sea 6, en vez de 7. eso significaría que el domingo sería 7 en lugar de pasar a 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;


... hay un calendario que ya tiene el lunes como el primer día de la semana, en lugar del domingo.

Algún día, habrá.


Abajo también cubre la caja de borde,

- (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]; }


El calendario ISO 8601 parece tener su primer día de la semana establecido en lunes de manera predeterminada.


El problema con la respuesta de Kris es el caso límite en el que el comienzo de la semana comienza en el mes anterior. Aquí hay un código más fácil y también verifica el borde del caso:

// 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]; }


En mi opinión, esta configuración debe ser dinámica de acuerdo con la configuración regional del usuario. Por lo tanto, uno debe usar:

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

Esto hará que el calendario se configure el primer día de la semana según la configuración regional del usuario automáticamente. A menos que esté desarrollando su aplicación para un propósito específico / ubicación del usuario (o prefiera permitir que el usuario elija este día).


Este código construye una fecha que está configurada para el lunes de la semana actual:

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


Iv descubrió la manera de mostrar cualquier nombre de día de la semana usando nscalender..utilizando el siguiente código. Simplemente abra la consola desde la barra de menú de xcode para ver los resultados. Copie Pegue el siguiente código en su método viewDidLoad para obtener el primer día de la semana

NSDate *today = [NSDate date]; NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; [dateFormat setDateFormat:@"MM/dd/yyyy :EEEE"]; NSString *dateString = [dateFormat stringFromDate:today]; NSLog(@"date: %@", dateString); [dateFormat release]; NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDateComponents *components = [gregorian components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:today]; [components setDay:([components day]-([components weekday]-1))]; NSDate *beginningOfWeek = [gregorian dateFromComponents:components]; NSDateFormatter *dateFormat_first = [[NSDateFormatter alloc] init]; [dateFormat_first setDateFormat:@"MM/dd/yyyy :EEEE"]; NSString *dateString_first = [dateFormat_first stringFromDate:beginningOfWeek]; NSLog(@"First_date: %@", dateString_first);

El resultado será:

date: 02/11/2010 :Thursday First_date: 02/07/2010 :Sunday

ya que ejecuté este programa el 2/11/2010 obtendrá la salida deseada dependiendo de la fecha actual.

Del mismo modo, si desea obtener el primer día hábil de la semana, es decir, la fecha del lunes, simplemente modifique el código un poco:

CAMBIO: [components setDay:([components day]-([components weekday]-1))];

TO [components setDay:([components day]-([components weekday]-2))];

para obtener la fecha de los lunes de esa semana ...

De forma similar, puede intentar encontrar la fecha de cualquiera de los siete días laborables cambiando el número entero -1, -2 y así sucesivamente ...

Espero que tu pregunta sea respondida ..

Gracias, Bonson Dias


Lo he hecho así.

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


Mi forma simple de hacer esto es obtener el lunes = 0, el domingo = 6:

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


Prueba esto:

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


Solo puede cambiar .firstWeekday del calendario.

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

Luego use rangeOfUnit:startDate:interval:forDate: para obtener el primer día

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


Tuve problemas con muchas de las respuestas aquí. . Tal vez era sólo yo. .

Aquí hay una respuesta que funciona para mí:

- (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]; }

Actualizar:

Como se señaló (en elsewhere ) por @vikingosegundo, en general es mejor dejar que el local determine qué día es el inicio de la semana, sin embargo, en este caso, el OP estaba pidiendo que el inicio de la semana ocurriera el lunes, por lo tanto copiamos el calendario del sistema, y ​​anula el primer WeekDay.


Uso del calendario nextWeekend (iOS 10 o posterior) y ordinality (gracias @ kris-markel). He recibido el lunes como el primero de la semana para el calendario en_US.

Aquí hay un ejemplo de esto con la opción de volver a 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 } }


Veo malentendidos en los otros mensajes. El primer día de la semana, cualquiera que sea, tiene el número 1 no 0. Por defecto Sunday = 1 como en la "Guía de programación de introducción a la fecha y hora para Cocoa: cálculos calendáricos":

"El valor del día de la semana para el domingo en el calendario gregoriano es 1"

Para el lunes como primer día de trabajo, el único remedio que tengo es la condición de fuerza bruta para arreglar el cálculo

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;


Editar: Esto no verifica el caso límite donde comienza el comienzo de la semana en el mes anterior. Algunos códigos actualizados para cubrir esto: https://.com/a/14688780/308315

En caso de que alguien todavía esté prestando atención a esto, debes usar

ordinalityOfUnit:inUnit:forDate:

y establecer firstWeekday en 2. (1 == Domingo y 7 == Sábado)

Aquí está el código:

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);

Recuerde, los ordinales para los días de semana comienzan en 1 para el primer día de la semana, no en cero.

Enlace de documentación .


setFirstWeekday: en el objeto NSCalendar. Establece el índice del primer día de la semana para el receptor.

- (void)setFirstWeekday:(NSUInteger)weekday

Debería hacer el truco.