iphone - medio - Nil NSDate al intentar obtener la fecha de la cadena UTC en tiempo zulu
utc gmt (7)
Al escribir una aplicación de iPhone en Objective-C, tengo una fecha en formato de cadena (en formato UTC, con una Z en el extremo para indicar un desplazamiento UTC cero, o tiempo zulú), que debo analizar en un objeto NSDate
.
Un poco de código:
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];
Ejecutando esto a través del depurador, ¡la date
termina en nil
! Supongo que tiene algo que ver con mi cadena de formato de fecha.
¿Cómo puedo arreglarlo para analizar correctamente la cadena de fecha?
Un pensamiento sería hacer que la Z
en el formato de la fecha sea literal, a la vez que se establece el formato de la fecha en yyyy-MM-dd''T''HH:mm:ss.SSS''Z''
.
Eso funcionaría, excepto cuando la Z se analiza como un literal, la fecha pierde información de compensación y, por lo tanto, es ambigua y, por lo tanto, se interpreta como hora local.
Por ejemplo, si la cadena a analizar era 2009-08-11T06: 00: 00.000Z (6:00 hora zulú) se interpretaría como 6:00 hora local y se aplicaría un desplazamiento incorrecto. Luego se analizará como 2009-08-11T06: 00: 00.000-600 (12:00 zulu time) con el desplazamiento en función del desplazamiento del usuario.
¡Gracias!
Creo que necesitas poner comillas simples alrededor de la Z en la cadena de formato, porque la Z en realidad significa algo para el formateador y quieres que represente un carácter literal.
[df setDateFormat:@"yyyy-MM-dd''T''HH:mm:ss.SSS''Z''"];
Esto puede ayudarte. La "Z" es un literal para el código de zona horaria. intente usar "o" (la letra, no cero). El literal "o" significa desplazamiento UTC. Me encontré con esto hace un tiempo, espero que esto te haya ayudado.
La mayoría de las respuestas sugieren que se trate a ''Z'' como un carácter literal. ¡No hagas esto!
La Z en realidad significa que la fecha está desplazada en 0 a UTC (+0000).
Esto es de acuerdo con el formato de zona horaria ISO8601 :
Formato de zona horaria ISO 8601: un desplazamiento constante y específico de UTC, que siempre tiene el mismo formato, excepto UTC ("Z").
"-08: 00"
"Z"
Lo que desea hacer es usar el siguiente formato para su 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;
Al repetir la Z cinco veces, le indica al formateador que use ISO8601 al analizar la cadena.
Prima:
- Utilice de una a tres Z s para el formato RFC 822 GMT.
- Utilice cuatro Z s para el formato GMT localizado.
Para más información consulte this documento.
No hay necesidad de manipular la cadena. Simplemente configure la zona horaria en el NSDateFormatter
(y la configuración regional mientras está en ello):
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''"];
Y analizar las cadenas de fecha según sea necesario:
NSDate * value = [formatter dateFromString:@"2012-03-01T23:08:25.000Z"];
NSLog(@"%@", value); // prints 2012-03-01 23:08:25 +0000
Puede utilizar este método para obtener la fecha de 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]];
}
También he tenido este problema, no estoy seguro de si se trata de un error de API en el código de Apple o de mi falta de comprensión, pero he trabajado para solucionarlo mediante el uso de las compensaciones de hora en mis cadenas de fecha.
Si cambia el código en su ejemplo a:
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];
Ahora analizará la cadena de fecha. Por supuesto, las -0700 horas son mi desplazamiento, tendrías que cambiarlo por el tuyo. Espero que esto ayude.
-(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;
}