Domanda

L'analisi di una data rfc3339 con NSDateFormatter sembra essere impossibile, nel caso generale. Ho sbagliato? [Edit 2 anni dopo: ora c'è un modo! Vedi sotto e la nota.]

Un servizio web non-particolarmente malleabile mi sta alimentando risale come:

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

Rfc3339 compatibile, uscita di default della biblioteca JAXB che stanno usando. Si noti il ??colon, che rfc3339 richiede , quando l'offset non è una "z" letterale:

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

Voglio analizzare questi in NSDates.

NSDateFormatter vuole modelli nella sintassi specificato da Unicode , che offre simboli della data di campo per i fusi orari come "PDT", "-0800", "GMT-08: 00", ma non "-08: 00".

Googling, e altre domande così simili, produce solo formati di data come

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

L'ultima delle quali richiede una "Z" letterale, e l'ex insiste l'assenza di un colon o presenza di un "GMT". Tuttavia, essi sembravano lavoro prima di iOS 4.x (eventualmente scartando l'offset completamente tz;. I miei dati non sono chiare)

Le mie opzioni a questo punto sono molto dispiaciuto:

  • scoprire un po 'di identificatore di formato non documentata, o qualche strano modo di mettere in NSDateFormatter, che accetta il colon randagi: Longshot, probabilmente inesistente. [Nota]
  • convincere il mio editore servizio per trasformare tutte le date nel tempo Zulu e specificare 'Z':. Politicamente impegnativo
  • scrivere il mio NSFormatter sottoclasse o di ricerca buon vecchio strptime_l: il lavoro. :)
  • string-manipolare il mio ingresso e striscia l'ultimo colon:. Fragile e brutto, ma il probabile percorso di minor resistenza

Ho capito la situazione con precisione, che l'attuale NSDateFormatter segue unicode rigorosamente senza estensioni; e il formato Unicode non sono sufficienti a descrivere completamente una data rfc3339?

[Nota] che torno a questo tre anni più tardi a virare su un piccolo addendum: Unicode e Apple hanno aggiunto questa caratteristica per le stringhe di formato, come di iOS6 / OSX10.8. Confronta L'ultima revisione al momento della stesura con il suo predecessore immediato e notare l'aggiunta di 5 "Z" s, da cui si ricava un formato zona come "-08: 00". Quindi, se si può ottenere via con l'ammaraggio, il supporto per 5.x / 10.7, c'è un nuovo modo giusto per farlo. Lascio lo stand precedente risposta, in quanto è ancora l'approccio migliore quando è richiesta la compatibilità all'indietro.

È stato utile?

Soluzione

Data all'analisi delle stringhe in Cocoa può essere un dolore, soprattutto se si ha a che fare con date generate da NET servizi web based.

Vorrei suggerire a guardare la categoria NSDate + InternetDateTime che Michael Waterfall ha sulla NSDate come parte del suo progetto MWFeedParser su GitHub. Ha funzionato bene per me l'analisi esattamente il formato della data che descrivi.

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

Altri suggerimenti

- getObjectValue: forString: gamma: errore: can date RFC3339 realtà analizzare correttamente. Non ho idea del perché - dateWithString: non può:

// 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];

I caratteri di formato stringa sono documentati da nessuna parte nella documentazione di Apple. Invece c'è un link nascosto nel profondo, in qualche punta documento allo standard Unicode a

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

Utilizzando le informazioni in quel collegamento è abbastanza semplice:

- (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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top