2010-11-03 19 views
6

Estoy escribiendo una categoría en Xcode, que extendería la clase NSDate actual. Quiero agregar dos métodos que utilizo regularmente y de alguna manera no puedo hacer que funcionen correctamente.Obtener NSDate para hoy con 00:00:00 como hora

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 vuelva una fecha como esta: "2010-11-03 00:00:00 01". Pero de alguna manera la zona horaria me sigue molestando, porque este código devuelve "2010-11-02 23:00:00 +0000".

¿Alguien puede decirme cómo corregir este código para realmente devolver la fecha correcta? ¿O puedo usar esta fecha y mi aplicación la convertirá a sí misma debido a la zona horaria en la que está configurada la máquina?

Tengo que registrar ciertos eventos en mi aplicación en una base de datos, que también usa el método [NSDate date]. ¿Eso significa que el método [NSDate date] también usa el tiempo 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 tiene la aplicación Clock, y el error hace que la gente se despierte tarde. Además, TimeZone se configura por defecto en TimeZone actualmente configurado en su dispositivo, por lo que debe permanecer igual hasta que cambie la zona horaria en la pantalla de configuración.

Edit2: bien, algunas pruebas 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 

Respuesta

5

Ver Using Time Zones. Deberá configurar el huso horario del calendario con el método -setTimeZone: de NSCalendar antes de comenzar a solicitar fechas.

+0

Nozzi ... realmente? ¿Me estás siguiendo? :PAG. Creo que tiene algo que ver con el error del horario de verano. Las cosas que veo son exactamente las mismas que probablemente tiene la aplicación Clock, y el error hace que la gente se despierte tarde. –

+0

No conozco a esta persona @jnozzi de Twitter que mencionaste. ¿Qué? No lo mencionaste? ¡MALDITA SEA! Oh, bueno, sí, soy yo. ;-) Hmm. No escuché sobre eso. Es posible que desee etiquetar el iPhone cuando use material de Foundation, ya que Mac/iOS no está claro en esos casos. :-) –

+0

Muhaha, sé dónde encontrarlo en todas partes. Actualicé mi publicación nuevamente. ¿Realmente necesito AGREGAR ese desplazamiento cuando llamo a [NSDate date]? Esperaba que el sistema operativo hiciera eso automáticamente. –

0

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

El problema probablemente sea en el formato de la fecha de salida devuelta. Te ha dado una cadena para GMT en lugar de tu configuración regional actual.

1

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

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

PS si no hay otra solución que ha encontrado basado en la sugerencia de Joshua, ¿podría hacernos saber lo que es? Parece que has resuelto el problema desde que aceptaste su respuesta, pero no está claro qué hiciste. ¡Gracias!

3

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

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

incluya la palabra clave tendrá el mismo resultado que el código se muestra a continuación:

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

lectura a través de la NSDate Class Reference produce esta documentación en el método de la de NSDatedescription.

No se garantiza que la representación se mantenga constante en las diferentes versiones del sistema operativo. Para dar formato a una fecha, se debe utilizar un objeto de fecha formateador en su lugar (consulte la Guía NSDateFormatter y formateo de datos)

También me encontré con la documentación de descriptionWithLocale: (id) locale:

“Devuelve una representación de cadena del receptor usando la localidad dada.”

Así, cambie su código

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

:

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

que debería traducirse en lo que busca. Y también puedo probar que el [NSDate date] realmente da la fecha correcta, pero solo se muestra con el método incorrecto:

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

dateLastDay: 2010-11-02 23:59:00 +01
dateToday: 2010-11-03 24:01:00 +01

A continuación, utilizar el código de abajo para mostrar las dos fechas:

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

O:

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

Los dos grupos muestran los mismos resultados, como esto: "2010-11- 22:59:00 +0000" y "2010-11- 23:01:00 +0000". Parece que las dos fechas tienen el mismo "día", ¿pero realmente?

Ahora comparamos el día de la fecha:

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 fechas parecen tener el mismo día, mes y año, NO LO HACEN. Solo aparece de esa manera porque los mostramos de la manera incorrecta.

2

¿Usted intentó usando:

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