Obtener NSDate para hoy con 00:00:00 como hora

Estoy escribiendo una categoría en Xcode, que extenderá la class NSDate actual. Quiero agregar dos methods que uso regularmente y de alguna manera no puedo hacer que funcionen correctamente.

Actualmente tengo este código:

+ (NSDate*) today { NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDateComponents *todayComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:[NSDate date]]; NSInteger theDay = [todayComponents day]; NSInteger theMonth = [todayComponents month]; NSInteger theYear = [todayComponents year]; NSDateComponents *components = [[NSDateComponents alloc] init]; [components setDay:theDay]; [components setMonth:theMonth]; [components setYear:theYear]; NSDate* todayDate = [gregorian dateFromComponents:components]; [components release]; [gregorian release]; return todayDate; } 

Quiero que regrese una date como esta: "2010-11-03 00:00:00 +01". Pero de alguna manera la zona horaria me falla, porque este código devuelve "2010-11-02 23:00:00 +0000".

¿Alguien puede decirme cómo corregir este código para devolver la date correcta? O puedo usar esta date y mi aplicación la convertirá por la zona horaria en la que está configurada la máquina.

Tengo que registrar ciertos events en mi aplicación en una database, que también utiliza el método [Fecha de la date]. ¿Significa eso que el método [Fecha NSDate] también usa el time sin información de zona horaria?

EDIT: Creo que tiene algo que ver con el error del horario de verano. Las cosas que veo son exactamente las mismas que probablemente tengan la aplicación Clock, con el error haciendo que las personas se despierten tarde. Además, la zona horaria establece de manera pnetworkingeterminada la zona horaria establecida actualmente en su dispositivo, por lo que debe permanecer igual hasta que cambie la zona horaria en la pantalla de configuration.

EDIT2: Ok, algunas testings más:

 NSLog(@"CurrentDate: %@", [NSDate date]); NSLog(@"TZ: %@", [NSTimeZone defaultTimeZone]); 

Me da los siguientes resultados:

 2010-11-03 23:23:49.000 App[8578:207] CurrentDate: 2010-11-03 22:23:49 +0000 2010-11-03 23:23:49.001 App[8578:207] TZ: Europe/Amsterdam (GMT+01:00) offset 3600 

Consulte Uso de zonas horarias . Deseará establecer la zona horaria del calendar utilizando el método NSCalendar -setTimeZone: antes de comenzar a preguntarle por las dates.

Esta es una pregunta interesante y trabajé en una solución durante muchas horas. Estos son mis hallazgos:

 NSLog(@"CurrentDate: %@", [NSDate date]); 

El código que se muestra arriba tendrá el mismo resultado que el código que se muestra a continuación:

 NSLog(@"CurrentDate: %@", [[NSDate date] description]); 

La lectura a través de NSDate Class Reference produce esta documentation en el método de description de NSDate .

No se garantiza que la representación se mantenga constante en diferentes versiones del sistema operativo. Para formatear una date, debe usar un object formateador de date (consulte NSDateFormatter y la Guía de formatting de datos)

También encontré la documentation para descriptionWithLocale: (id) locale :

"Devuelve una representación de cadena del receptor usando la configuration regional dada".

Entonces, cambia tu código

 NSLog(@"CurrentDate: %@", [NSDate date]); 

A:

 NSLog(@"CurrentDate: %@", [[NSDate date] descriptionWithLocale:[NSLocale currentLocale]]); 

Lo que debería dar como resultado lo que está buscando. Y también puedo demostrar que la [NSDate date] realmente da la date correcta, pero solo se muestra con el método incorrecto:

Podemos usar el [today] (Wim Haanstra) para crear dos dates.

date de la última jornada : 2010-11-02 23:59:00 +01
date hoy : 2010-11-03 24:01:00 +01

Luego usamos el código a continuación para mostrar las dos dates:

 NSLog(@"CurrentDate: %@", dateLastDay); NSLog(@"CurrentDate: %@", dateToday); 

O:

 NSLog(@"CurrentDate: %@", [dateLastDay description]); NSLog(@"CurrentDate: %@", [dateToday description]); 

Los dos grupos muestran los mismos resultados, así: "2010-11- 02 22:59:00 +0000" y "2010-11- 02 23:01:00 +0000". Parece que las dos dates tienen el mismo "día", pero ¿de verdad?

Ahora comparamos los días de las dates:

 NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSUInteger unitFlags = NSDayCalendarUnit; NSDateComponents *lastDayComponents = [gregorian components:unitFlags fromDate:dateLastDay]; NSDateComponents *todayComponents = [gregorian components:unitFlags fromDate:dateToday]; NSInteger lastDay = [lastDayComponents day]; NSInteger today = [todayComponents day]; return (lastDay == today) ? YES : NO; 

¡Obtendremos NO! Aunque las dos dates parecen tener el mismo día, mes y año, NO. Solo aparece de esa forma porque los mostramos de manera incorrecta.

¿Intentaste usar:

 NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"yyyy-MM-dd"]; todayAtOO = [formatter dateFromString:[formatter stringFromDate:[NSDate date]]]; 

Todavía estoy tratando de averiguar exactamente por qué ocurre este error, pero sí sé una solución. Configurar la zona horaria de su NSCalendar a GMT antes de enviarla dateFromComponents: resolverá el problema.

 [gregorian setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; 

PS si hay una solución diferente que encontraste basada en la sugerencia de Joshua, ¿podrías dejarnos saber qué es? Parece que has resuelto el problema desde que aceptaste su respuesta, pero no está claro qué hiciste. ¡Gracias!

Por lo que puedo ver, te está dando la respuesta correcta si tu zona horaria es GMT + 1. La medianoche su hora es las 23:00 del día anterior en GMT.

Probablemente el problema sea formatear la date devuelta para la salida. Le ha dado una cadena para GMT en lugar de su location actual.