2010-02-04 22 views
46

Si utilizo el siguiente código:¿Existe una manera simple de convertir una marca de tiempo ISO8601 en un formato NSDate?

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm"]; 
NSDate *myDate = [dateFormatter dateFromString:@"2010-01-28T15:22:23.863"]; 
NSLog(@"%@", [dateFormatter stringFromDate:myDate]); 

Se convirtió con éxito a un objeto Date, sin embargo, me parece que no puede formatear cualquier otra manera que yyyy-MM-dd'T'HH:mm, es decir, lo que se registrado es 2010-01-28T15:22:23

Si Cambio el dateFormat para decir [dateFormatter setDateFormat:@"yyyy-MMMM-d'T'HH:mm"]; el objeto Date es nulo ...

Así que mi pregunta final es cómo formatear una marca de tiempo ISO8601 de una base de datos SQL para usar, por ejemplo, NSDateFormatterMediumStyle para devolver "Januar y 1, 2010 "?

Respuesta

19

Necesita otro formateador para manejar la salida. Ponga esto después de su código:

NSDateFormatter *anotherDateFormatter = [[NSDateFormatter alloc] init]; 
[anotherDateFormatter setDateStyle:NSDateFormatterLongStyle]; 
[anotherDateFormatter setTimeStyle:NSDateFormatterShortStyle]; 
NSLog(@"%@", [anotherDateFormatter stringFromDate:myDate]); 
5

Debo señalar que la última vez que lo comprobé Manzanas NSDate métodos no apoyó ISO8601. Todavía tengo un error con Apple acerca de poner la ayuda oficial en.

+ (id)dateWithNaturalLanguageString:(NSString *)string

serán adecuadamente (la última vez que lo dirigió) analizar y crear un objeto a partir de una cadena NSDate ISO801, aunque la documentación dice que no debería Úselo, ha funcionado en todas las fechas ISO8601 que he intentado hasta ahora.

+0

Es cierto que '+ (id) dateWithNaturalLanguageString: (NSString *) cadena 'analizará correctamente a menos que haya milis en su cadena ISO8601. –

+1

Debo añadir que nunca debes usar esto ahora. En el momento en que usé esto, estaba funcionando, pero desde entonces he pasado a usar otras API que funcionan de manera confiable con ISO8601. dateWithNaturalLanguageString funciona con ISO8601, pero solo por accidente, no confíe en que continuará funcionando en el futuro. –

42

Tengo un problema similar pero un poco más complejo, ¡y he encontrado una solución muy simple!

El problema: Mis fechas entrantes ISO8601 aspecto: 2006-06-14T11:06:00+02:00 Tienen un corrector en la zona horaria final.

La solución: Uso de Peter Hosey ISO8601DateFormatter que se puede descargar desde here.

ISO8601DateFormatter *formatter = [[ISO8601DateFormatter alloc] init]; 
NSDate *theDate = [formatter dateFromString:dateString]; 
[formatter release], formatter = nil; 

y

ISO8601DateFormatter *formatter = [[ISO8601DateFormatter alloc] init]; 
NSString *dateString = [formatter stringFromDate:[twitch dateTwitched]]; 
[formatter release], formatter = nil; 
+3

ISO8601DateFormatter funciona bien, pero es extremadamente lento. En mis pruebas, el análisis que tomó NSDateFormatter 300ms tomó ISO8601DateFormatter 7400ms. –

+0

@SamSoffes 7 segundos? No debería llevar tanto tiempo para una sola fecha. ¿Puede proporcionar más detalles, por favor? (Preferiblemente en un informe de error: https://bitbucket.org/boredzo/iso-8601-parser-unparser) –

+4

Actualización: ahora es [mucho más rápido] (http://t.co/mT25yJpX). No más de 7-8 segundos. –

19

Aquí es código de ejemplo de la manzana

NSDateFormatter * formatter = [[NSDateFormatter alloc] init]; 
    [formatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"]; 
    NSDate *date = [formatter dateFromString:dateString]; 

enlace: https://developer.apple.com/library/ios/#qa/qa1480/_index.html

+1

No olvides configurar la configuración regional POSIX como se menciona en ese artículo de Apple; de lo contrario, podría terminar con fechas no conformes que incluyen "AM" o "PM", si el usuario tiene una combinación extraña de configuraciones (por ejemplo, configuración regional del Reino Unido con tiempo de 12 horas habilitado). –

+1

Si se necesitan milisegundos, utilice @ "yyyy '-' MM '-' dd'T'HH ':' mm ':' ss '.' SSS'Z '" – HotJard

+1

@JoeHughes ¿Cómo configura la configuración regional POSIX? – jjxtra

12

Sólo para mencionar que desde iOS 6.0 se puede utilizar este formato:

yyyy-MM-dd'T'HH:mm:ssZZZZZ 
+1

¡Gracias por compartir con nosotros, justo lo que necesitaba! Fechas como 2013-06-28T15: 20: 55 + 02: 00 -> aaaa-MM-dd'T'HH: mm: ssZZZZZ – mmvie

+1

Lamentablemente esto no analiza los tiempos con la zona horaria UTC designada por una sola 'Z' en lugar de '+ hh: mm'. O lo hace? – macbirdie

+0

@macbirdie No creo que así sea, así es como se define http://www.unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns – Marcin

6

Tengo una implementación muy rápida de C de análisis ISO8601 NSStrings a NSDates en SAMCategories. Puede instalarlo con CocoaPods o simplemente copiar los archivos a su proyecto.

Así es como se usa:

[NSDate sam_dateFromISO8601String:@"2013-08-24T06:51:21-07:00"]

Es muy robusto y soporta las zonas horarias que faltan, etc. Como my comment above dijo, NSDateFormatter era muy lento para mí al analizar un montón de fechas.El cambio a esta implementación ayudó a una cantidad inmensa.

Este código se utiliza en 6 aplicaciones de producción (incluyendo Hipstamatic y Roon) en las que he trabajado sin problemas conocidos. Hay un test suite para evitar la regresión.

En resumen, creo que esta es la mejor manera de analizar cadenas ISO8601 en Objective-C.


Un corto a un lado, si usted está preocupado por el rendimiento y la transferencia, el envío de números enteros en lugar de cadenas ISO8601 se prefiere en gran medida. Simplemente puede convertirlos en fechas con [NSDate dateWithTimeIntervalSince1970:yourInteger]. El rendimiento es tan rápido como puede hacerlo y hay menos caracteres para transferir a través del cable.

+0

¿Existe una ventaja además de la legibilidad humana en el uso de ISO 8601 en lugar de una marca de tiempo entera? –

3

@danielbeard answer funcionó para mí. Sin embargo, debe incluir la zona horaria, de lo contrario, convertirá una fecha UTC en su zona horaria actual que no es la que desea.

- (NSDate *) dateFromISO8601DateString:(NSString *) dateString { 
    NSDateFormatter * dateFormatter = [NSDateFormatter new]; 
    dateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"UTC"]; 
    [dateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"]; 
    NSDate * date = [dateFormatter dateFromString:dateString]; 
    return date; 
} 
2

@Thread capitán Prueba este formato: "aaaa-MM-dd'T'HH: mm: SS.sss"

Cuestiones relacionadas