Pregunta

Analizar una fecha rfc3339 con NSDateFormatter parece ser imposible, en el caso general. ¿Me equivoco? [Editar 2 años más tarde: ahora hay una manera! Véase más abajo y la nota.]

Un servicio web no-especialmente maleable me está alimentando fechas como:

2009-12-31T00:00:00-06:00

compatible Rfc3339, salida por defecto de la biblioteca jaxb que están usando. Nota del colon, que rfc3339 requiere cuando el desplazamiento no es un literal "z":

time-numoffset  = ("+" / "-") time-hour ":" time-minute
time-offset     = "Z" / time-numoffset

Quiero analizar estos en NSDates.

NSDateFormatter quiere patrones en la sintaxis especificada por Unicode , que ofrece símbolos campo de fecha para las zonas horarias como "PDT", "-0800", "GMT-08: 00", pero no "-08: 00".

buscar en Google, y otras cuestiones tan similares, produce sólo como formatos de fecha

[myDateParser setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"];
/* or: */ [myDateParser setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];

El último de los cuales requiere un literal "Z", y la antigua insiste ya sea la ausencia de un colon o presencia de una "GMT". Sin embargo, parecían trabajo antes de iOS 4.x (posiblemente descartando el desplazamiento completo tz;. Mis datos no son claras)

Mis opciones en este momento hay una gran cantidad siento:

  • descubrir algunos especificador de formato indocumentado, o de algún modo extraño para poner en NSDateFormatter, que aceptará el colon callejero: tiro largo, probablemente inexistente. [Nota]
  • persuadir a mi editor servicio para convertir todas las fechas en el tiempo zulú y especificar 'Z':. Desafío político
  • escribir mi propia NSFormatter subclase o investigación buena strptime_l de edad: el trabajo. :)
  • cadena de manipular mi entrada y despojar a la última de colon:. Quebradiza y feo, pero el camino de menor resistencia probable

¿He entendido correctamente la situación, que la corriente NSDateFormatter sigue estrictamente Unicode sin extensiones; y los formatos Unicode son insuficientes para describir completamente una fecha rfc3339?

[Nota] vuelvo a esto tres años más tarde para virar en una pequeña adición: Unicode y Apple han añadido esta característica para las cadenas de formato, a partir de iOS 6 / OSX10.8. Comparar La última revisión de este escrito con su predecesor inmediato , y tenga en cuenta la adición de 5 "Z" s, lo que da un formato zona como "-08: 00". Así que si usted puede conseguir lejos con zanjas apoyo a 5.x / 10,7, hay una nueva forma correcta de hacerlo. Voy a dejar el stand respuesta anterior, ya que sigue siendo el mejor enfoque cuando se requiere compatibilidad con versiones anteriores.

¿Fue útil?

Solución

Fecha procesamiento de cadenas de cacao puede ser un dolor, especialmente si usted tiene que tratar con fechas .NET generados por los servicios web basados.

Te sugiero mirar la categoría NSDate + InternetDateTime que Michael tiene Cascada en NSDate como parte de su proyecto MWFeedParser en github. Ha funcionado bien para mí analizar exactamente el formato de fecha que usted describe.

https://github.com/mwaterfall/MWFeedParser/

Otros consejos

- getObjectValue: forString: Gama: error: ¿Pueden las fechas RFC3339 realidad analiza correctamente. No tengo ni idea de por qué - dateWithString: no puede:

// RFC3339 date formatting
NSString *dateString = @"2012-04-11T18:34:19+00:00";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";

NSDate *date;
NSError *error;
[formatter getObjectValue:&date forString:dateString range:nil error:&error];

Los caracteres de formato de cadena están documentados en ninguna parte de la documentación de Apple. En cambio, hay un vínculo oculto en algún documento que apunta hacia el estándar Unicode a

http://www.unicode.org/reports/tr35/tr35 -31 / TR35-dates.html # Date_Format_Patterns

El uso de la información en ese enlace es bastante simple:

- (NSDate*)dateFromRFC3339String:(NSString*)aString
{
    static NSDateFormatter* sRFC3339DateFormatter = nil;
    static NSDateFormatter* sRFC3339DateFormatterSubSeconds = nil;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];

        sRFC3339DateFormatter = [[NSDateFormatter alloc] init];
        [sRFC3339DateFormatter setLocale:enUSPOSIXLocale];
        [sRFC3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssXXXXX"];
        [sRFC3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];

        sRFC3339DateFormatterSubSeconds = [[NSDateFormatter alloc] init];
        [sRFC3339DateFormatterSubSeconds setLocale:enUSPOSIXLocale];
        [sRFC3339DateFormatterSubSeconds setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSSXXXXX"];
        [sRFC3339DateFormatterSubSeconds setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
    });

    NSDate* date = [sRFC3339DateFormatter dateFromString:aString];
    if (date == nil)
        date = [sRFC3339DateFormatterSubSeconds dateFromString:aString];

    return date;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top