Nil NSDate quando si cerca di ottenere data da stringa UTC in tempo zulu
-
13-09-2019 - |
Domanda
Scrivere un applicazione per iPhone in Objective-C, ho un appuntamento in forma di stringa (in formato UTC, con una Z sulla fine per indicare lo zero UTC offset, o il tempo zulu), che ho bisogno di analizzare in un oggetto NSDate
.
Un po 'di codice:
NSDateFormatter* df = [[NSDateFormatter alloc]init];
[df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
NSString* str = @"2009-08-11T06:00:00.000Z";
NSDate* date = [df dateFromString:str];
L'esecuzione di questo tramite il debugger, date
finisce nil
! Sto assumendo che abbia qualcosa a che fare con la mia data stringa di formato. Come posso risolvere il problema di analizzare correttamente la stringa di data?
Un pensiero sarebbe quello di rendere il
Z
nel formato data letterale, alla impostare il formato della data per yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
. Che avrebbe funzionato, se non quando la Z viene analizzato come un letterale, la data perde insieme di informazioni, e così è ambiguo, e quindi interpretata come ora locale.
Ad esempio, se la stringa da analizzare era 2009-08-11T06: 00: 00.000Z (6:00 tempo zulu), viene interpretato 6:00 ora locale, e sarebbe poi applicato un corretto compensato. Sarebbe quindi essere analizzato come 2009-08-11T06: 00:. 00.000-600 (12:00 ora zulu) con la funzione offset della compensazione
utente Grazie!
Soluzione
Ho avuto questo problema anche, non sono sicuro se si tratta di un bug nel codice API di Apple, o la mia mancanza di comprensione, ma ho lavorato intorno ad esso utilizzando offset ora nelle mie stringhe di data.
Se si modifica il codice nel tuo esempio:
NSDateFormatter* df = [[NSDateFormatter alloc]init];
[df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
NSString* str = @"2009-08-11T06:00:00.000-0700"; // NOTE -0700 is the only change
NSDate* date = [df dateFromString:str];
E 'ora analizzare la stringa data. Naturalmente i -0700 ore è compensato il mio, dovresti cambiarlo al tuo. Spero che questo aiuti.
Altri suggerimenti
La maggior parte delle risposte suggeriscono di trattare 'Z' come carattere letterale. non farlo!
La Z significa in realtà che la data è compensato da 0 a UTC (0000).
Questo è in base al formato zona ISO8601 :
formato ISO 8601 zona di tempo:. Una costante, offset da UTC, che ha sempre lo stesso formato tranne UTC stessa ( "Z")
specifica"- 08:00"
"Z"
Che cosa si vuole fare è utilizzare il seguente formato per il vostro NSDateFormatter:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// 2013-11-18T23:00:00.324Z
[formatter setTimeZone:[NSTimeZone localTimeZone]];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"];
return formatter;
Ripetendo il Z per cinque volte, ti dicono il formattatore di utilizzare ISO8601 durante l'analisi della stringa.
Bonus:
- Utilizza 02:59 Z s per RFC 822 formato GMT.
- Utilizza quattro Z per s formato GMT localizzato.
Per ulteriori informazioni consulta questo documento .
Credo che hai bisogno di mettere le virgolette singole intorno alla Z nella stringa di formato, perché la Z in realtà significa qualcosa per il formattatore e lo si vuole rappresentare un carattere letterale, invece.
[df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
Non c'è bisogno di manipolare la stringa. Basta impostare il fuso orario sul NSDateFormatter
(e il locale, mentre si è in esso):
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[formatter setLocale:[NSLocale systemLocale]];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
E analizzare le stringhe di data in base alle esigenze:
NSDate * value = [formatter dateFromString:@"2012-03-01T23:08:25.000Z"];
NSLog(@"%@", value); // prints 2012-03-01 23:08:25 +0000
È possibile utilizzare questo metodo per ottenere la data da UTC.
+ (NSDate*)getDateFromUTCDateTimeString:(NSString*)dateString {
NSDateFormatter *isoDateFormatter = [[NSDateFormatter alloc] init];
[isoDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
[isoDateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
NSDateFormatter *userFormatter = [[NSDateFormatter alloc] init];
[userFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
NSDate *date = [isoDateFormatter dateFromString:dateString];
return [dateFormatter dateFromString:[userFormatter stringFromDate:date]];
}
questo può aiutare .. il "Z" è un valore letterale per il codice del fuso orario. provare a utilizzare "o" (la lettera, non zero). Il letterale "o" significa Offset UTC. Mi sono imbattuto in questo un po 'indietro, spero che questo ti ha aiutato.
-(NSDate*)dateFromZulu:(NSString*)str {
if (str == nil) {
NSLog(@"Error getting date");
return [NSDate date];
}
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss Z"];
NSDate *ret = [f dateFromString:[str stringByReplacingOccurrencesOfString:@"Z" withString:@" +0000"]];
[f release];
if (ret == nil) {
ret = [NSDate date];
NSLog(@"Error formatting date (%@)",str);
}
return ret;
}