CoreData& NSDate - 日期在2015年落后1天

时间:2014-07-23 09:29:40

标签: ios core-data nsdate nscalendar nsdatecomponents

我真的很难过应该是什么东西真的很简单。我的应用程序的一个功能是每月重复事件,所以我需要一个日期,添加一个月,并存储它。每个月我都会重复这个。

我遇到的问题是我在测试时发现,当日期超过2015年3月时它会失去一天 - 所以3月22日变成3月21日...... 4月...... 5月等。更奇怪的事情一旦我过了2016年3月,它就会回到第22位 - 不再错过一天。

它不能是夏令时,因为它发生在12个月或闰年,因为2015年不是闰年,据我所知。

我正在使用MagicalRecord来帮助CoreData,我很确定它可能与CoreData本身有关吗?这是调用更新日期的简单代码:

// create date if we haven't already
    if (!_dateEntity.theDate) {
        NSDate *date = [NSDate date];
        _dateEntity.theDate = date;
    }

    NSLog(@"date before update - %@", _dateEntity.theDate);

    // add a month to it
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setMonth:1];
    _dateEntity.theDate = [calendar dateByAddingComponents:components toDate:_dateEntity.theDate options:0];

    NSLog(@"date after update - %@ \n ***** \n", _dateEntity.theDate);

    // save the context
    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
        if (success) {
            //NSLog(@"You successfully saved your context.");
        } else if (error) {
            //NSLog(@"Error saving context: %@", error.description);
        }
    }];

这是半sudo代码,从实际项目中删除到一个独立的项目中进行测试(以确保我不会生气!)

这里(根据要求)是来自xCode的日志:

2014-07-23 10:48:55.001 dateTest[52136:60b] date before update - 2014-07-23 09:48:54 +0000
2014-07-23 10:48:55.003 dateTest[52136:60b] date after update - 2014-08-23 09:48:54 +0000 
 ***** 
2014-07-23 10:48:59.994 dateTest[52136:60b] date before update - 2014-08-23 09:48:54 +0000
2014-07-23 10:48:59.995 dateTest[52136:60b] date after update - 2014-09-23 09:48:54 +0000 
 ***** 
2014-07-23 10:49:04.685 dateTest[52136:60b] date before update - 2014-09-23 09:48:54 +0000
2014-07-23 10:49:04.686 dateTest[52136:60b] date after update - 2014-10-23 09:48:54 +0000 
 ***** 
2014-07-23 10:49:08.127 dateTest[52136:60b] date before update - 2014-10-23 09:48:54 +0000
2014-07-23 10:49:08.128 dateTest[52136:60b] date after update - 2014-11-23 10:48:54 +0000 
 ***** 
2014-07-23 10:49:12.594 dateTest[52136:60b] date before update - 2014-11-23 10:48:54 +0000
2014-07-23 10:49:12.595 dateTest[52136:60b] date after update - 2014-12-23 10:48:54 +0000 
 ***** 
2014-07-23 10:49:16.014 dateTest[52136:60b] date before update - 2014-12-23 10:48:54 +0000
2014-07-23 10:49:16.015 dateTest[52136:60b] date after update - 2015-01-23 10:48:54 +0000 
 ***** 
2014-07-23 10:49:20.188 dateTest[52136:60b] date before update - 2015-01-23 10:48:54 +0000
2014-07-23 10:49:20.189 dateTest[52136:60b] date after update - 2015-02-23 10:48:54 +0000 
 ***** 
2014-07-23 10:49:32.956 dateTest[52136:60b] date before update - 2015-02-23 10:48:54 +0000
2014-07-23 10:49:32.957 dateTest[52136:60b] date after update - 2015-03-23 10:48:54 +0000 
 ***** 
2014-07-23 10:49:44.061 dateTest[52136:60b] date before update - 2015-03-23 10:48:54 +0000
2014-07-23 10:49:44.061 dateTest[52136:60b] date after update - 2015-04-23 09:48:54 +0000 
 ***** 

从日志中,一切看起来都很好 - 仍然在23日(今天)。但是,如果我实际查看数据库本身,则2015-03-23和2015-04-23的最后两个日期分别显示为2015-03-22和2015-04-22。

数据库中的最新更新,如SQL浏览器中所示: 2015/04/22 10:48:54

他们将在2016年3月之前表现得像这样,此时他们将回归正确存储。这是我真的不明白的一点。

有没有经历过这样的事情?我现在正在撕开我的头发

1 个答案:

答案 0 :(得分:0)

我认为这确实是夏令时问题,而不是核心数据问题。当间隔跨越标准时间到达夏令时时,您的时间间隔计算会给您带来意想不到的结果。

试试这个例子,没有核心数据:

    NSDate *dateNow = [NSDate date];

    // add a month to it
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setMonth:1];
    components.calendar = calendar;
    NSDate *dateNowPlusOneMonth = [calendar dateByAddingComponents:components toDate:dateNow options:0];

    NSLog(@"now %@", dateNow);
    NSLog(@"now plus one month %@", dateNowPlusOneMonth);

    NSDate *dateMarch01 = [NSDate dateWithTimeIntervalSince1970:1425206934];
    // add a month to it
    NSDate *dateMarch01PlusOneMonth = [calendar dateByAddingComponents:components toDate:dateMarch01 options:1];
    NSLog(@"Interval straddles ST/DST changeover date in USA");
    NSLog(@"March 01 %@", dateMarch01);
    NSLog(@"March 01 plus one month %@", dateMarch01PlusOneMonth);

    NSDate *dateMarch23 = [NSDate dateWithTimeIntervalSince1970:1427107734];
    // add a month to it
    NSDate *march23PlusOneMonth = [calendar dateByAddingComponents:components toDate:dateMarch23 options:0];
    NSLog(@"Interval is after ST/DST changeover date in USA");
    NSLog(@"March 23 %@", dateMarch23);
    NSLog(@"March 23 plus one month %@", march23PlusOneMonth);

这里是输出(删除了NSLog时间戳):

now 2014-07-23 18:03:22 +0000
now plus one month 2014-08-23 18:03:22 +0000

Interval straddles ST/DST changeover date in USA
March 01 2015-03-01 10:48:54 +0000
March 01 plus one month 2015-04-01 09:48:54 +0000

Interval is after ST/DST changeover date in   USA
March 23 2015-03-23 10:48:54 +0000
March 23 plus one month 2015-04-23 10:48:54 +0000

要添加到此问题的卑鄙性质,您将在程序中看到不同的结果,具体取决于用户的时区(实际是DST更改日期)。澳大利亚,英国和美国的错误行为都会略有不同!

日期和时间编程指南的清单10说明"在本周获得星期日"。我认为您需要调整该程序,例如"获取下个月的当前日期和时间"。