NSDateFormatter, ¿estoy haciendo algo mal o es esto un error?

Estoy tratando de imprimir la fecha en un formato determinado:

NSDate *today = [[NSDate alloc] init]; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyyMMddHHmmss"]; NSString *dateStr = [dateFormatter stringFromDate:today]; 

Si el iPhone está configurado en 24 horas, funciona bien, si por otro lado el usuario lo configuró en 24 horas, luego vuelve a AM / PM (funciona bien hasta que se alterna esta configuración) y luego agrega el AM / PM al final aunque no lo pedí:

 20080927030337 PM 

¿Estoy haciendo algo mal o es un error con el firmware 2.1?

Edición 1: descripción más clara

Editar 2 solución alternativa: resulta que es un error, para solucionarlo configuré los caracteres AM y PM en “”:

 [dateFormatter setAMSymbol:@""]; [dateFormatter setPMSymbol:@""]; 

Usando el código que publicó tanto en el simulador como en un teléfono con el firmware 2.1 y el horario de 24 horas desactivado, nunca tuve un AM / PM adjunto a dateStr cuando lo hago:

 NSLog(@"%@", dateStr); 

¿Estás haciendo algo más con dateStr que no publicaste aquí? ¿Cómo estás controlando el valor?

Seguir

Intente encender y apagar el ajuste am / pm. Yo tampoco tuve el problema, hasta que lo hice. Lo estoy imprimiendo de la misma manera que tú.

De acuerdo, lo veo cuando hago esto también. Tiene que ser un error. Le recomiendo que presente un informe de error y solo revise y filtre los caracteres no deseados mientras tanto.

La razón de este comportamiento es Locale, establece la configuración regional correcta, establece el local de NSDateFormatter en en_US_POSIX corregirá esto. Funciona para formatos de 24 horas y 12 horas.

On iPhone OS, the user can override the default AM/PM versus 24-hour time setting (via Settings > General > Date & Time > 24-Hour Time), which causes NSDateFormatter to rewrite the format string you set. De apple doc

Prueba esto,

 NSDate *today = [[NSDate alloc] init]; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]]; [dateFormatter setDateFormat:@"yyyyMMddHHmmss"]; NSString *dateStr = [dateFormatter stringFromDate:today]; 

Aquí está la explicación del error de iPhone SDK (también está todavía en 3.1 beta SDK)

En primer lugar, un poco de historia en la interfaz de usuario de iPhone. Cuando los usuarios de iPhone cambian su formato de región entre, digamos, “Estados Unidos” y “Francia”, la configuración de “24 horas” de los usuarios cambia automáticamente al modo que prevalece más en esa región. En Francia, eso establecería la Hora de 24 horas en “ENCENDIDO”, y en los EE. UU., Eso lo pondría en “DESACTIVADO”. Los usuarios pueden anular manualmente esa configuración y ahí es donde comienzan los problemas.

El problema proviene de que NSDateFormatter se “atasca” de alguna manera en el modo de 12 o 24 horas que el usuario ha seleccionado manualmente. Entonces, si un usuario francés selecciona manualmente el modo de 12 horas, y la aplicación solicita a NSDateFormatter tiempo de salida con el formato de 24 horas “HHmm”, en realidad recibiría el tiempo en un formato de 12 horas, por ejemplo, “01:00 PM”, como si la aplicación hubiera solicitado “hhmm aa”. Lo contrario ocurriría si un usuario estadounidense selecciona manualmente el modo de 24 horas: el tiempo de salida con el formato de 12 horas “hhmm aa” realmente le daría tiempo en el formato de 24 horas, por ejemplo, “17:00”.

Se pueden encontrar más detalles y una posible solución en este blog .

Configurar el entorno local en el formateador de fecha en en_US me soluciona el problema:

  NSDateFormatter * f = [[NSDateFormatter alloc] init]; [f setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; f.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; f.calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease]; f.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"] autorelease]; 

No estoy seguro si también se necesita agregar el calendario, pero esto funciona bien.

Creo que esta es la solución.

 NSDateFormatter *df =[[NSDateFormatter alloc] init]; [df setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; [df setLocale: usLocale]; [usLocale release]; NSDate *documento_en_Linea =[[[NSDate alloc] init]autorelease]; documento_en_Linea=[df dateFromString:@"2010-07-16 21:40:33"]; [df release]; NSLog(@"fdocumentoenLineaUTC:%@!",documento_en_Linea); //ouput fdocumentoenLineaUTC:2010-07-16 09:40:33 pm -0500! 

Para aquellos que encuentran esta pregunta y quieren usar NSDateFormatter para analizar el tiempo de 24 horas y están llegando a este error, el uso de NSDateComponents para analizar las fechas y horas que tienen un formato conocido evita este problema:

 NSString *dateStr = @"2010-07-05"; NSString *timeStr = @"13:30"; NSDateComponents *components = [[NSDateComponents alloc] init]; components.year = [[dateStr substringToIndex:4] intValue]; components.month = [[dateStr substringWithRange:NSMakeRange(5, 2)] intValue]; components.day = [[dateStr substringFromIndex:8] intValue]; components.hour = [[timeStr substringToIndex:2] intValue]; components.minute = [[timeStr substringFromIndex:3] intValue]; NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDate *date = [calendar dateFromComponents:components]; [components release]; [calendar release]; 

Esto también debería funcionar (aunque estoy viendo algunos resultados extraños).

 -(NSString*)lowLevTime:(NSString*)stringFormat { char buffer[50]; const char *format = [stringFormat UTF8String]; time_t rawtime; struct tm * timeinfo; time(&rawtime); timeinfo = localtime(&rawtime); strftime(buffer, sizeof(buffer), format, timeinfo); return [NSString stringWithCString:buffer encoding:NSASCIIStringEncoding]; } 

Respuesta corta: prueba [dateFormatter setDateFormat:@"yyyyMMddhhmmss"]; para el formato de 12 horas (tenga en cuenta la letra hh minúscula).

Ha sido un tema frustrante porque muchos sitios web indican usar HH por horas (incluida la documentación oficial de Apple), pero eso lo configura en formato de 24 horas, mientras que hh usa el formato de 12 horas. Ver http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns para más detalles.

Como beneficio adicional, tenga en cuenta que también puede usar KK o kk para el formato de hora del día, que probablemente estará desactivado en uno.

Actualización: Hace poco estuve mirando NSLocale (https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSLocale_Class/Reference/Reference.html) y parece que puede usar autoupdatingCurrentLocale para aplicar los cambios realizados desde la aplicación a la configuración regional. El resultado de esto es que incluso si el teléfono está configurado para usar un reloj de 24 horas (como cuando cambiaste a Francia), puedes hacer un alternar 12/24 para la aplicación que no afectará a ninguna otra aplicación en el teléfono, o requiere que abandones la aplicación para realizar el cambio.