【问题标题】:NSDateFormatter's dateFromString returning null with date from stringFromDate [duplicate]NSDateFormatter 的 dateFromString 返回 null 与来自 stringFromDate 的日期 [重复]
【发布时间】:2015-10-27 08:22:13
【问题描述】:

我在尝试在 NSDictionary 中添加 nil 日期时发生了崩溃。

我的代码如下所示:

625  NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
626  NSCalendar *currentCalendar = [NSCalendar autoupdatingCurrentCalendar];
627  NSDate *todayDate = [NSDate date];
628
629  NSDateComponents *dateComponents = [currentCalendar components:NSUIntegerMax fromDate:todayDate];
630
631  NSMutableArray *lastDates = [[NSMutableArray alloc] init];
632
633  dateFormatter.dateFormat = @"y-M-d";
634
635  for (NSInteger i = 0; i < 7; i++) {
636      NSDate *date = [currentCalendar dateFromComponents:dateComponents];
637
638      dateComponents.day--;
639
640      [lastDates addObject:[dateFormatter stringFromDate:date]];
641  }
642
643  NSString *query = @"SELECT date FROM table";
644  NSArray *completedDates = [ZeeSQLiteHelper readQueryFromDB:query];
645
646  NSMutableDictionary *completedLessons = [[NSMutableDictionary alloc] init];
647
648  for (NSString *date in lastDates) {
649      BOOL completed;
650
651      if ([completedDates containsObject:@{ @"date" : date }]) {
652          completed = YES;
653   } else {
654       completed = NO;
655   }
656
657   completedLessons[[dateFormatter dateFromString:date]] = @(YES); // crash
658  }

出于某种原因,有时dateFromString: 返回nil 并崩溃。

崩溃报告:

0     CoreFoundation      0    x231d068b    __exceptionPreprocess + 124
1     libobjc.A.dylib     0    x3458ae17    objc_exception_throw + 36
2     CoreFoundation      0    x230ec8fb    -[__NSDictionaryM setObject:forKey:] + 840
3     MyApp               0    x00148df7    -[MyClass myMethod] (MyClass.m:657)
4     MyApp               0    x001406f3    -[MySecondViewController mySecondVCMethod] (MySecondViewController.m:250)
5     MyApp               0    x0013f8ed    -[MySecondViewController viewDidLoad] (MySecondViewController.m:92)
6     UIKit               0    x2729443d    -[UIViewController loadViewIfRequired] + 1106
7     UIKit               0    x27293fcd    -[UIViewController view] + 22
8     UIKit               0    x27abb559    -[_UIFullscreenPresentationController _setPresentedViewController:] + 70
9     UIKit               0    x275c9339    -[UIPresentationController initWithPresentedViewController:presentingViewController:] + 110
10    UIKit               0    x275ec473    -[UIViewController _presentViewController:withAnimationController:completion:] + 3536
11    UIKit               0    x275eeac5    __62-[UIViewController presentViewController:animated:completion:]_block_invoke + 334
12    UIKit               0    x275eed31    -[UIViewController _performCoordinatedPresentOrDismiss:animated:] + 414
13    UIKit               0    x27388701    -[UIViewController presentViewController:animated:completion:] + 142
14    MyApp               0    x00223429    -[MyFirstViewController myFirstVCSecondMethod] (MyFirstViewController.m:775)
15    MyApp               0    x00221edb    -[MyFirstViewController myFirstVCFirstMethod:] (MyFirstViewController.m:631)
16    UIKit               0    x272ca795    -[UIApplication sendAction:to:from:forEvent:] + 78
17    UIKit               0    x272ca725    -[UIControl sendAction:to:forEvent:] + 62
18    UIKit               0    x272b354b    -[UIControl _sendActionsForEvents:withEvent:] + 444
19    UIKit               0    x272ca085    -[UIControl touchesEnded:withEvent:] + 602
20    UIKit               0    x27286d33    _UIGestureRecognizerUpdate + 10768
21    UIKit               0    x272c36f9    -[UIWindow _sendGesturesForEvent:] + 902
22    UIKit               0    x272c2e43    -[UIWindow sendEvent:] + 620
23    UIKit               0    x272947e5    -[UIApplication sendEvent:] + 202
24    UIKit               0    x27292fdf    _UIApplicationHandleEventQueue + 4932
25    CoreFoundation      0    x23193c3f    __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12
26    CoreFoundation      0    x2319382d    __CFRunLoopDoSources0 + 450
27    CoreFoundation      0    x23191b9b    __CFRunLoopRun + 792
28    CoreFoundation      0    x230e5249    CFRunLoopRunSpecific + 518
29    CoreFoundation      0    x230e5035    CFRunLoopRunInMode + 106
30    GraphicsServices    0    x2c1c8ad1    GSEventRunModal + 158
31    UIKit               0    x272fa899    UIApplicationMain + 142
32    MyApp               0    x00152f83    main (main.m:16)
33    libdyld.dylib       0    x34cd6873    start + 0

另外,我有 99% 的把握这发生在巴西,10 月 18 日,Daylight Saving Time occured

【问题讨论】:

  • 尝试打印您的日期字符串并验证其格式是否与您使用的格式相同,即 y-M-d
  • 我不能,我通过Crittercism 得到崩溃报告。我自己无法重现它。但从外观上看,没有外在因素,应该是可以的。
  • 对于解决方法,您可以在添加到字典之前检查日期不为空..
  • 我已经将你的代码编译了 10 次,它从未崩溃过。
  • @IulianOnofrei:根据日期格式,您会丢失信息。例如,使用日期格式 y-M-d,您会丢失时间和时区信息。

标签: ios objective-c nsdateformatter


【解决方案1】:

This answer 和@DarkDust 的comment 为我指明了正确的方向。

巴西的夏令时确实是在午夜时分出现的问题。因此,在 10 月 17 日至 18 日期间,没有午夜。因此,因为我将日期格式设置为 y-M-ddateFromString: 试图返回本地午夜的日期,但该日期不存在,因此它返回了 nil

重现步骤:

dateFormatter.timeZone = [NSTimeZone timeZoneWithName:@"America/Sao_Paulo"];
NSLog([dateFormatter dateFromString:@"2015-10-18"]); // returns nil

我仍然需要找到一个解决方案,让我在这个时区返回像 2015-10-18 01:00:00 这样的日期。

【讨论】:

  • 啊,乔恩的回答是我忘记的经典……因为您可以检测到由于nil 返回或使用getObjectValue:forString:range:error: which returns an error in the NSCocoaErrorDomain 导致的错误,您可以通过附加时间和下降来修改字符串回到包含时间的不同日期格式化程序。您可能还想尝试CFDateFormatter:也许它有同样的问题,也许没有。
  • @DarkDust,我可以做类似dateComponents.hour = 8 的事情,但它会在 100% 的时间内解决它吗?
  • 我猜你不能确定。我们今天可以查看时区信息,并可能确定是的,它每次都可以工作。但是下次Kim Jong-Un smokes too much pot 或其他国家提出一些愚蠢的事情时呢?由于它是一个很少发生的问题的后备方案,因此使用这种解决方法可能是相当安全的。但可能解决此问题的最佳方法是通过在第一个循环中存储字符串和日期来完全消除对 dateFromString: 的调用。
猜你喜欢
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多