2010-12-01 7 views
8

Estoy escribiendo una aplicación que utiliza datos centrales para almacenar mis datos. Incluido en este es un campo de fecha del cual solo me interesa la fecha, no el momento. necesito para seleccionar registros en base a la fecha (no la hora) y por eso he creado una categoría de NSDate para devolver una fecha, normalizada a una hora determinada de la siguiente manera:Práctica recomendada de NSDate al crear una fecha sin elemento de tiempo

+ (NSDate *)dateWithNoTime:(NSDate *)dateTime { 
if(dateTime == nil) { 
    dateTime = [NSDate date]; 
} 
NSDateComponents* comps = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:dateTime]; 
NSDate *dateOnly = [[NSCalendar currentCalendar] dateFromComponents:comps]; 
[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)];   // Push to Middle of day. 
return dateOnly; 

}

que entonces Úselo cuando agregue datos al almacén de datos básicos (tengo un sistema que usa este método para establecer el valor de fecha primitiva) y luego uso este método para crear una fecha que utilizo para comparar las fechas cuando realizo una solicitud de recuperación . Entonces, en teoría, esto siempre debería funcionar, es decir, elegir las fechas que estoy buscando.

Estoy un poco nervioso, aunque no estoy totalmente seguro de qué efecto tendrá el cambio de zona horaria o localidad. ¿Seguirá funcionando?

Lo que se considera la mejor práctica al almacenar y buscar en una fecha solo cuando no está interesado en el momento.

Saludos.

EDITAR

Después de leer la discusión recomienda Creo que debo modificar mi código para ser el siguiente. La idea es que si me aseguro de llevarlo a un sistema de calendario específico y una zona horaria específica (UTC), las fechas siempre deben ser las mismas independientemente de dónde se encuentre cuando configure la fecha y cuando lea la fecha. Cualquier comentario sobre este nuevo código apreciado.

+ (NSDate *)dateWithNoTime:(NSDate *)dateTime { 
if(dateTime == nil) { 
    dateTime = [NSDate date]; 
} 

NSCalendar  *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease]; 
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; 
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease]; 
components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit 
         fromDate:dateTime]; 

NSDate *dateOnly = [calendar dateFromComponents:components]; 

[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)];   // Push to Middle of day. 
return dateOnly; 

}

+0

¡Gracias por la solución! : D Sólo una pequeña corrección: La línea: '[dateOnly dateByAddingTimeInterval: (60,0 * 60,0 * 12,0)];' debe ser: 'dateOnly = [dateOnly dateByAddingTimeInterval: (60,0 * 60,0 * 12,0)];' –

Respuesta

5

Usted tiene algunos problemas para hacer frente a aquí. Primero, como notaste, zonas horarias. También debe preocuparse por los ahorros de luz diurna, que cambian el concepto de "mediodía".

Mire this discussion en CocoaDev donde un ingeniero de Apple da algunas respuestas y analiza algunas de las mejores prácticas.

+0

Gracias por eso. Después de leer esa discusión, parece que debería asegurarme de usar siempre el mismo sistema de calendario y la misma zona horaria para almacenar y comparar. He agregado un nuevo código a mi pregunta basado en este nuevo pensamiento. – SimonB

3

Una solución más simple es usar un predicado que busque fechas dentro de un cierto rango.

Use NSCalendarComponent para crear una fecha de inicio y una fecha de finalización para su "día" y luego incluirlas en el predicado.

NSPredicate *p=[NSPredicate predicateWithFormat:@"[email protected] <= date <= [email protected]",startDate,endDate]; 

Eso proporcionará la flexibilidad máxima sin mucha complejidad. La programación de fecha y hora es engañosamente compleja. Prepárate para hacer un poco de trabajo.

2

También terminé en un escenario en el que necesitaba un NSDate para comparar una fecha sin tener en cuenta el tiempo.

Dispongo de un mecanismo de filtro y como parte de la IU, si el usuario eligió hoy la fecha mínima como fecha de inicio y fecha de finalización actual, mostraría "Todos los períodos" en lugar de una cadena en el formato :

1/5/2006 - 24/12/2009

así que necesitaba para tomar la fecha de hoy usando +date de NSDate, y compararlo con la fecha de finalización. Esa fecha final provino de un UIDatePicker establecido sin tiempo, pero +date devolvió la fecha y la hora de ahora.

Así que escribí este breve método útil, recibe un objeto de fecha, usa NSDateComponents y la clase NSCalendar para extraer el día, mes y año.

Estos 3 parámetros se utilizan a continuación para crear una nueva NSDate usando NSDateFormatter's - método dateFromString:, el resultado es una NSDate correspondiente a la misma "fecha" (en el concepto humano tradicional) como el parámetro de date pero sin tiempo.

- (NSDate *)strictDateFromDate:(NSDate *)date{ 
    NSUInteger flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; 
    NSDateComponents *components = [[NSCalendar currentCalendar] components:flags 
                    fromDate:[NSDate date]]; 
    NSString *stringDate = [NSString stringWithFormat:@"%d/%d/%d", components.day, components.month, components.year]; 

    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease]; 
    formatter.dateFormat = @"dd/MM/yyyy"; 

    return [formatter dateFromString:stringDate]; 
} 

Espero que pueda usar y disfrutar de esta función en el futuro.

+0

¡Intenté este pero también los valores de devolución contienen la marca de tiempo !!! –

Cuestiones relacionadas