Pergunta

Escrevendo um aplicativo para iPhone em Objective-C, eu tenho uma data na forma de string (em formato UTC, com um Z na extremidade para denotar de zero UTC offset, ou o tempo zulu), o que eu preciso analisar em um objeto NSDate .
Um pouco 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];
A execução deste através do depurador, date acaba nil! Eu estou supondo que ele tem algo a ver com a minha seqüência de formato de data.
Como posso corrigi-lo para corretamente analisar a cadeia de data?
Um pensamento seria fazer o Z no literal formato de data, a la definição do formato de data para yyyy-MM-dd'T'HH:mm:ss.SSS'Z'.
Que iria trabalhar, exceto quando o Z é analisado como um literal, a data perde informações offset, e assim é ambígua e, portanto, interpretado como hora local.
Por exemplo, se a string para analisar foi 2009-08-11T06: 00: 00.000Z (6:00 hora zulu) seria interpretado como 06:00 hora local, e um deslocamento incorreto, então, ser aplicada. Seria, então, ser analisado como 2009-08-11T06: 00:. 00.000-600 (12:00 zulu) com o deslocamento dependendo do deslocamento
usuário Thanks!

Foi útil?

Solução

Eu tive esse problema também, eu não tenho certeza se é um bug API no código da Apple, ou minha falta de compreensão, mas eu trabalhei em torno dele usando deslocamentos hora em minhas cordas data.

Se você alterar o código no seu exemplo para:

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

Ele vai agora analisar a cadeia de data. É claro que os -0700 horas é meu offset, você tem que mudá-lo para o seu. Espero que isso ajude.

Outras dicas

A maioria das respostas sugerem que você trate 'Z' como um caractere literal. Não faça isso!

O Z realmente significa que a data é compensada por 0 a UTC (+0000).

Este é de acordo com o formato de fuso horário ISO8601 :

8,601 tempo formato ISO zona:. Uma constante, deslocamento do UTC, que sempre tem o mesmo formato, excepto em si UTC ( "Z") específico

"- 08:00"

"Z"

O que você quer fazer é usar o seguinte formato para o seu 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;

Ao repetir o Z cinco vezes, você diz ao formatador usar ISO8601 ao analisar a string.

Bonus:

  • Use 1-3 Z s para RFC 822 formato GMT.
  • Use quatro Z s para formato GMT localizada.

Para obter mais informações verificação este documento .

Eu acho que você precisa colocar aspas simples ao redor do Z na string de formato, porque o Z realmente significa algo para o formatador e quer que ele para representar um caractere literal em seu lugar.

    [df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];

Não há necessidade de manipular a string. Basta definir o fuso horário no NSDateFormatter (e o local enquanto você está nisso):

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 cordas data de análise, conforme necessário:

NSDate * value = [formatter dateFromString:@"2012-03-01T23:08:25.000Z"];
NSLog(@"%@", value); // prints 2012-03-01 23:08:25 +0000

Você pode usar este método para obter data a partir 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]];

}

isso pode ajudá-lo .. o "Z" é um literal para o código de fuso horário. tente usar "o" (a letra, não zero). O literal "o" meio UTC offset. Corri para este um tempo atrás, eu espero que isso te ajudou.

-(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;     
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top