22

在 Objective-C 中编写 iPhone 应用程序时,我有一个字符串形式的日期(UTC 格式,末尾有一个 Z 表示零 UTC 偏移量或祖鲁时间),我需要将其解析为一个NSDate对象。

一点代码:

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];
通过调试器运行它,date结束nil!我假设它与我的日期格式字符串有关。

如何修复它以正确解析日期字符串?

一个想法是Z在日期格式中制作文字,将日期格式设置为yyyy-MM-dd'T'HH:mm:ss.SSS'Z'.

这会起作用,除非当 Z 被解析为文字时,日期会丢失偏移信息,因此不明确,因此被解释为本地时间。

例如,如果要解析的字符串是 2009-08-11T06:00:00.000Z(祖鲁时间 6:00),它将被解释为当地时间 6:00,然后应用不正确的偏移量。然后它将被解析为 2009-08-11T06:00:00.000-600(祖鲁时间 12:00),偏移量取决于用户的偏移量。

谢谢!

4

7 回答 7

28

我也遇到过这个问题,我不确定这是否是 Apple 代码中的 API 错误,或者我缺乏理解,但我已经通过在我的日期字符串中使用小时偏移来解决它。

如果您将示例中的代码更改为:

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

它现在将解析日期字符串。当然,-0700 小时是我的偏移量,您必须将其更改为您的。希望这可以帮助。

于 2009-08-12T00:34:14.603 回答
13

大多数答案建议您将“Z”视为文字字符。不要这样做!

Z 实际上意味着日期偏移 0 到 UTC (+0000)。

这是根据时区格式ISO8601

ISO 8601 时区格式:相对于 UTC 的恒定的特定偏移量,除了 UTC 本身(“Z”)外,它始终具有相同的格式。

“-08:00”

“Z”

您要做的是为您的 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;

通过重复Z五次,您可以告诉格式化程序在解析字符串时使用 ISO8601。

奖金:

  • 对 RFC 822 GMT 格式使用一到三个Z。
  • 使用四个Z表示本地化 GMT 格式。

有关更多信息,请查看文档。

于 2014-01-29T15:16:57.737 回答
4

我认为您需要在格式字符串中的 Z 周围加上单引号,因为 Z 实际上对格式化程序意味着什么,而您希望它代表一个文字字符。

    [df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
于 2009-08-12T08:21:08.250 回答
2

无需操作字符串。只需在NSDateFormatter(以及您使用时的区域设置)上设置时区:

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

并根据需要解析日期字符串:

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

您可以使用此方法从 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]];

}

于 2016-10-21T09:05:04.867 回答
0

这可能会对您有所帮助..“Z”是时区代码的文字。尝试使用“o”(字母,而不是零)。文字“o”表示 UTC 偏移量。前段时间遇到了这个问题,希望对你有帮助。

于 2009-11-21T20:31:27.887 回答
-1
-(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;     
}
于 2010-04-30T20:21:35.547 回答