【问题标题】:iOS NSDateFormatter dateFromString returns nil only in one instanceiOS NSDateFormatter dateFromString 仅在一个实例中返回 nil
【发布时间】:2014-03-09 00:49:38
【问题描述】:

NSDateFormatter 是否有意外返回 nil 的倾向?我不认为它没有。 我希望我忽略了一些由于某种原因我看不到的微小细节。

我有一些描述太阳和月亮的数据。它在下面列出。 我还有一个循环,一旦它从它的 plist 加载到字典中,它就会迭代这个数据。 最后我有一个类,它使用 NSDateFormatter 作为单例为我处理日期。 这个过程运行得很好,这些方法已经交互并产生正确的日期一两个月,但今天它崩溃了。通过这个简单过程创建和传递的所有字符串都正确转换为日期,除了最后一个为 nil 的字符串。 事情是这样的:

这是属性列表中的数据。

<key>2014-3-7</key>
<dict>
    <key>moonrise</key>
    <string>10:51 am</string>
    <key>moonset</key>
    <string>0:03 am</string>
    <key>phase</key>
    <string>Waxing Crescent</string>
    <key>sunrise</key>
    <string>6:39 am</string>
    <key>sunset</key>
    <string>6:21 pm</string>
</dict>

<key>2014-3-8</key>
<dict>
    <key>moonrise</key>
    <string>11:39 am</string>
    <key>moonset</key>
    <string>0:56 am</string>
    <key>phase</key>
    <string>First Quarter</string>
    <key>sunrise</key>
    <string>6:38 am</string>
    <key>sunset</key>
    <string>6:21 pm</string>
</dict>

<key>2014-3-9</key>
<dict>
    <key>moonrise</key>
    <string>1:28 pm</string>
    <key>moonset</key>
    <string>2:45 am</string>
    <key>phase</key>
    <string></string>
    <key>sunrise</key>
    <string>7:37 am</string>
    <key>sunset</key>
    <string>7:22 pm</string>
</dict>

这个数据是通过一个循环处理的,从昨天开始到明天结束的日期字符串创建日期,所以在这种情况下,它从 7 日或 3 月 7 日开始,到 9 日结束,我们正在处理每个 plist 项中的值将给定日期作为一个名为 iDay 的字典。

NSString *eventString;
NSDate *moonrise;
NSDate *moonset;
NSString *dateFormatString = @"yyyy-MM-dd h:mm a";

if ([iDay objectForKey:@"moonrise"] != nil) {
    eventString = [NSString stringWithFormat:@"%@ %@", dateString, [iDay objectForKey:@"moonrise"]];
    moonrise = [self.dateTime makeDateFromString:eventString
                                          format:dateFormatString];
}

if ([iDay objectForKey:@"moonset"] != nil) {
    eventString = [NSString stringWithFormat:@"%@ %@",dateString, [iDay objectForKey:@"moonset"]];
    moonset = [self.dateTime makeDateFromString:eventString
                                         format:dateFormatString];
}

这些语句传递给 [self.dateTime makeDateFromString] 的字符串如下所示:

2014-3-7 上午 10:51

2014-3-7 上午 0:03

2014-3-8 上午 11:39

2014-3-8 上午 0:56

2014-3-9 下午 1:28

2014 年 3 月 9 日凌晨 2:45

好的,很好。现在是 dateTime 单例:

+(ADateTimeClass *) sharedDateTime {
    @synchronized(self)
    {
        if (sharedInstance == NULL)
            sharedInstance = [[self alloc] init];
    }
    return sharedInstance;
}

-(id) init{
    self = [super init];
    if(self){
        self.dateFormat = [NSDateFormatter new];
        self.dateFormat.timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
    }
    return self;
}

... 以及这一切都发生了可怕错误的方法。传递给此方法的所有字符串都作为日期正确返回,除了最后一个,我检查过,nil 来自 "[dateFormat dateFromString:dateString]" 就在这里,其中 dateString 是我上面列出的六个之一。

-(NSDate*) makeDateFromString:(NSString *)dateString format:(NSString *)format{
    [dateFormat setDateFormat:format];
    NSDate* aDate = [dateFormat dateFromString:dateString];
    return aDate;
}

结果:

月出打印说明:2014-03-07 14:51:00 +0000

月落打印说明:2014-03-07 04:03:00 +0000

月出打印说明:2014-03-08 15:39:00 +0000

月落打印说明:2014-03-08 04:56:00 +0000

月出打印说明:2014-03-09 16:28:00 +0000

月落打印说明:

【问题讨论】:

  • 您能否还显示导致此问题的确切实例(并且可能将那些与创建日期一起工作的实例)?类似NSLog(@"Date from \"%@\" is \"%@\".", string, date);
  • 从您的输入(2014-3-7 10:51 am)和相应的输出(2014-03-07 14:51:00 +0000)看来您没有使用日期格式化程序由sharedDateTime 创建,因此在UTC中进行转换。
  • 大家好。是的,我明白你在说什么。我需要重新检查一下。 rmaddy 是对的,而且我巧妙地忘记了夏令时,这似乎很明显。感谢您指出差异。我会回复的。
  • 是的,时区是错误的,但我给你的这些值也是错误的。该例程将匹配的日期返回给我,例如 10:51 == 10:51,但新日期被标记为 AST 或 ADT,唯一的失败是在丢失的时间中正好落在那里的日期。

标签: ios objective-c nsdateformatter


【解决方案1】:

这实际上是一个简单的问题,具体取决于您居住的地方。至少在美国,由于夏令时更改,从 2014 年 3 月 9 日凌晨 2 点到 2:59 之间的任何时间都不会存在。因此任何这样的日期都是无效的。

【讨论】:

  • 不幸的是,似乎没有很好的方法来检测这一点,因为您需要一个日期来测试它以确定它是否是 DST。似乎我需要 a) 以一种不必要的复杂方式执行此操作,通过使用 NSCalendar 将 DST 考虑在内,b) 确保我真的使用的是 UTC。
  • 您需要将日期格式化程序设置为语言环境 en_US_POSIX 以防止受到用户偏好的干扰。
  • @NFG:对于日期计算,您应该始终使用日历,因为日历将时间点(由 NSDate 实例表示)转换为有意义的时间和日期。它是一个知道天数的日历,而不是 nsdate 对象。
  • @NFC:另一种选择是在 NSDateComponents 上进行所有计算。视频中也有介绍。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
  • 1970-01-01
  • 2020-01-31
相关资源
最近更新 更多