【问题标题】:NSDateFormatter fails with string that seems correctNSDateFormatter 失败,字符串似乎正确
【发布时间】:2014-03-31 18:04:49
【问题描述】:

给定以下代码:

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
NSLog(@"Date from String: %@", [formatter dateFromString:@"2013-09-08T00:36:40"]);

日志产生:Date from String: (null)

对于来自同一来源的其他字符串,它可以工作,但我不明白为什么在这种情况下会失败。

有人可以启发我吗?

更新:我已经更新代码如下,还是失败:

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
[formatter setLocale:locale];

NSDate *date = nil;
NSError *error = nil;

[formatter getObjectValue:&date
                         forString:@"2013-09-08T00:36:40"
                             range:NULL
                             error:&error];

NSLog(@"Date from String: %@", date);
NSLog(@"Error: %@", error);

输出: 2014-03-31 15:27:01.697 无标题 [30859:507] 来自字符串的日期:(空) 2014-03-31 15:27:01.710 无标题 [30859:507] 错误:错误域 = NSCocoaErrorDomain 代码 = 2048 “值“2013-09-08T00:36:40”无效。”用户信息=0x7f89d8e04cd0 {NSInvalidValue=2013-09-08T00:36:40}

更新 2:经过一番玩弄后,我发现我的时区是它失败的原因(我不明白为什么,但它只在我的时区下失败)

以下代码失败:

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
[formatter setLocale:locale];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"America/Santiago"]];

NSDate *date = nil;
NSError *error = nil;

[formatter getObjectValue:&date
                         forString:@"2013-09-08T00:36:40"
                             range:NULL
                             error:&error];

NSLog(@"Date from String: %@", date);
NSLog(@"Error: %@", error);

有什么解决办法吗?

【问题讨论】:

  • 我无法重现您的问题,但我已在您更新后通过结束投票撤回。
  • 那么,第二种情况记录了什么?
  • 我也无法重现您的问题。我认为你应该考虑@MartinR 链接。
  • @pawan:他已经尝试过了(见更新的问题)。它没有帮助。

标签: objective-c cocoa foundation


【解决方案1】:

导致该错误的原因是智利地区下不存在该日期(由于 DST 更改)。

虽然 NSDateFormatter 返回 nil 是正确的,因为它不存在。告诉用户“该文件是在您的时区从未经历过的时间创建的”是不可行的。

解决方案(适用于任何其他有 DST 的区域)是设置一个时区,就像没有 DST 的当前时区一样。

NSString *dateString = ...; //Assume it is defined
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
[formatter setLocale:locale];
//Date formatting might fail because of Daylight Saving Timezones and the like. So, we force the timezone to one just like it where the date always exist.
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:[[NSTimeZone localTimeZone] secondsFromGMT]]];

NSDate *date = nil;
NSError *error = nil;

[formatter getObjectValue:&date
                         forString:dateString
                             range:NULL
                             error:&error];

同样,这在技术上是不正确的,但出于显示目的这样做是可以的。

【讨论】:

    【解决方案2】:

    根据http://www.timeanddate.com/time/zone/chile/santiago,夏令时 “America/Santiago”时区从 2013 年的 9 月 8 日星期日 00:00 开始,这意味着时钟提前一小时调整到 9 月 8 日星期日 01:00。

    因此,当天不存在“00:36:40”时间。这就是原因 转换失败。

    一个可能的解决方案是用给定的组件填充NSDateComponents 然后拨打dateFromComponents:

    NSCalendar *cal = [NSCalendar currentCalendar];
    [cal setTimeZone:[NSTimeZone timeZoneWithName:@"America/Santiago"]];
    NSDateComponents *comp = [[NSDateComponents alloc] init];
    comp.year = 2013;
    comp.month = 9;
    comp.day = 8;
    comp.hour = 0;
    comp.minute = 36;
    comp.second = 40;
    NSDate *d = [cal dateFromComponents:comp];
    NSLog(@"Date from components: %@", d);        //  2013-09-08 04:36:40 +0000
    NSString *s = [formatter stringFromDate:d];
    NSLog(@"String from date: %@", s);            //  2013-09-08T01:36:40
    

    这为所有“有效”日期字符串提供了相同的日期,而且结果也很合理 对于夏令时转换期间的“无效”日期字符串。

    【讨论】:

    • 我想可能是当我发现它是因为时区。但我仍然需要显示日期。我将发布我找到的适合我需要的解决方案。
    • @DiegoTorres:我找到了一个不同的解决方法,也许你可以使用它。
    • 在我的情况下它不会很容易工作,因为我仍然需要解析提供的字符串。不错的解决方法。
    猜你喜欢
    • 2013-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多