Analisi date rfc3339 con NSDateFormatter in iOS 4.xe MacOS X 10.6: impossibile?
-
30-09-2019 - |
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.
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.
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;
}