这周在做数据库迁移(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