0%

NSDate读取相差31年的问题

这周在做数据库迁移(v1.sqlite to v2.sqlite,需求:更改数据库里面某个字段的值,数据库用的是coredata,在读取数据库、迁移是用的是FMDB)时,遇到一个比较奇怪的bug(其实一点都不奇怪,只怪自己图样图生破)。就是时间字段(coredata存储的是NSDate对象)迁移后的年份是1985年(比如:原数据库的时间是2016.2.26,而迁移后却是1985.2.26),百事不得其解……后面查到原因是因为Apple NSDate对象存储的时候不是以1970.1.1作为基准,而是以2001.1.1作为基准的,详情请看下面。

1
NSDate objects encapsulate a single point in time, independent of any particular calendrical system or time zone. Date objects are immutable, representing an invariant time interval relative to an absolute reference date (00:00:00 UTC on 1 January 2001).

摘自NSDate Class Reference,所以上面相差31年的问题得到了解释。

当时我想用最暴力、最原始的方法,写个方法在某个NSDate对象上面直接加31年,因为时间赶嘛,但是想想觉得这个还是太恶心了,不厚道。后面查了 NSDate Class Reference才得以根本解决。

1
2
3
4
/// method 1
[NSDate dateWithTimeIntervalSinceReferenceDate:date.timeIntervalSince1970];
/// method 2
[date dateByAddingTimeInterval:NSTimeIntervalSince1970];

date就是用FMDB取出来的数据.

虽然问题得到了解决,但还是遇到一个问题,当数据库存储的是1、2月份的时间时,按照上面的方法转换会比存储的多一天,但是其他月份就没有这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
NSString *timeString1 = @"1985-02-28 09:12:23";
NSTimeInterval timeStamp1 = 477882743;
NSDate *stampDate1 = [NSDate dateWithTimeIntervalSince1970:timeStamp1];

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *date11 = [dateFormatter dateFromString:timeString1];
NSDate *date12 = [NSDate dateWithTimeIntervalSinceReferenceDate:date11.timeIntervalSince1970];
NSDate *date13 = [date11 dateByAddingTimeInterval:NSTimeIntervalSince1970];
NSLog(@"\ndate11:%@ \ndate12:%@ \ndate13:%@ \nstampDate1:%@ ",date11,date12,date13,stampDate1);
/*
date11:1985-02-28 01:12:23 +0000
date12:2016-02-29 01:12:23 +0000
date13:2016-02-29 01:12:23 +0000
stampDate1:1985-02-22 01:12:23 +0000
*/

NSString *timeString2 = @"1985-03-28 09:12:23";
NSTimeInterval timeStamp2 = 480647543;
NSDate *stampDate2 = [NSDate dateWithTimeIntervalSince1970:timeStamp2];
NSDate *date21 = [dateFormatter dateFromString:timeString2];
NSDate *date22 = [NSDate dateWithTimeIntervalSinceReferenceDate:date21.timeIntervalSince1970];
NSDate *date23 = [date21 dateByAddingTimeInterval:NSTimeIntervalSince1970];
NSLog(@"\ndate21:%@ \ndate22:%@ \ndate23:%@ \nstampDate2:%@ ",date21,date22,date23,stampDate2);
/*
date21:1985-03-28 01:12:23 +0000
date22:2016-03-28 01:12:23 +0000
date23:2016-03-28 01:12:23 +0000
stampDate2:1985-03-26 01:12:23 +0000
*/

时间戳我是用http://tool.chinaz.com/Tools/unixtime.aspx根据上面的时间获取的,这个问题模拟器和真机都存在。我没有找到原因,个人猜想,应该是闰年、平年的原因,因为1985年2月只有28天,2016年2月有29天,如果读者你知道原因,麻烦告诉我,thx。

参考链接

NSDate Class Reference