用户
 找回密码
 立即注册

发帖

NSDate读取相差31年的问题

[复制链接]
  • TA的每日心情
    慵懒
    2025-11-24 10:46
  • 27

    主题

    6

    回帖

    669

    积分

    管理员

    积分
    669
    发表于 2016-3-4 00:00:00
    这周在做数据库迁移(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作为基准的,详情请看下面。0 ~- k1 e2 O0 q  W/ y1 F
    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 ~$ y3 d0 b8 ?9 h" W
    1. /// method 1
      - ^5 D% Z/ n, Y0 o! V. w
    2. [NSDate dateWithTimeIntervalSinceReferenceDate:date.timeIntervalSince1970];
      9 R, A- E+ x( D+ |0 o/ `
    3. /// method 2
      7 H9 U0 D& N. J) s! {! o9 o* U
    4. [date dateByAddingTimeInterval:NSTimeIntervalSince1970];
    复制代码
    date就是用FMDB取出来的数据.
    虽然问题得到了解决,但还是遇到一个问题,当数据库存储的是1、2月份的时间时,按照上面的方法转换会比存储的多一天,但是其他月份就没有这个问题。
    " i1 K( x- Y$ `5 W" [
    1. NSString *timeString1 = @"1985-02-28 09:12:23";& m, U" z, K# G' K/ O& b4 D
    2. NSTimeInterval timeStamp1 = 477882743;
      # p9 A. ~# z  |# f; A/ c
    3. NSDate *stampDate1 = [NSDate dateWithTimeIntervalSince1970:timeStamp1];& H8 t& _4 T; m- k1 A# J' C- h
    4. ' M7 {% M8 {  f. `
    5. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
      ' k) a& L( P% F  I+ G4 }
    6. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
      7 I$ d% \- q. j3 F; H$ }0 I
    7. NSDate *date11 = [dateFormatter dateFromString:timeString1];
      " P* q& [; Z7 k1 S
    8. NSDate *date12 = [NSDate dateWithTimeIntervalSinceReferenceDate:date11.timeIntervalSince1970];
      * G4 r3 s2 I) J( U
    9. NSDate *date13 = [date11 dateByAddingTimeInterval:NSTimeIntervalSince1970];
      4 i: P+ U/ M3 F4 o7 ~9 D8 Z& u
    10. NSLog(@"\ndate11:%@ \ndate12:%@ \ndate13:%@ \nstampDate1:%@ ",date11,date12,date13,stampDate1);
      2 r1 D! v0 B+ T/ h* C: X
    11. /*
      " G. F3 A" _8 Y& }
    12. date11:1985-02-28 01:12:23 +0000 - L2 V2 v. k, b4 K
    13. date12:2016-02-29 01:12:23 +0000 6 b* p% l. i" q; y! o
    14. date13:2016-02-29 01:12:23 +0000
      $ _4 `+ F3 K. T" p- t; P" |; ^. N) p
    15. stampDate1:1985-02-22 01:12:23 +0000 & `0 w) q" e% o+ e  p3 f2 y- i
    16. */
      0 Y" L0 z  H, S( k1 l! q

    17. ; h, q# X/ |( n- ]! p# x7 ~
    18. NSString *timeString2 = @"1985-03-28 09:12:23";$ c! d! d8 s6 K: k- B+ Q8 o1 Q
    19. NSTimeInterval timeStamp2 = 480647543;
      ! t+ ~( E# l9 ^' O; u4 x' Z2 V* r
    20. NSDate *stampDate2 = [NSDate dateWithTimeIntervalSince1970:timeStamp2];0 j! J- f4 T1 E- g7 x: I
    21. NSDate *date21 = [dateFormatter dateFromString:timeString2];
      $ i* U8 u3 k: l
    22. NSDate *date22 = [NSDate dateWithTimeIntervalSinceReferenceDate:date21.timeIntervalSince1970];
      , g) L6 r+ Y4 _; z) |3 D- e
    23. NSDate *date23 = [date21 dateByAddingTimeInterval:NSTimeIntervalSince1970];
      % Q9 a5 J7 j* v% C
    24. NSLog(@"\ndate21:%@ \ndate22:%@ \ndate23:%@ \nstampDate2:%@ ",date21,date22,date23,stampDate2);
      , C" d4 u( H* j
    25. /*. q( R% @1 j. p3 n) E) N
    26. date21:1985-03-28 01:12:23 +0000 - O4 A$ ]' T! [! I
    27. date22:2016-03-28 01:12:23 +0000
      4 s( Z$ f. ]( U7 Z7 ~3 p( l
    28. date23:2016-03-28 01:12:23 +0000 + A; l1 C: i/ q. {% L
    29. stampDate2:1985-03-26 01:12:23 +0000
      & @& d& J1 g; H) ?  N; h
    30. */
    复制代码
    时间戳我是用http://tool.chinaz.com/Tools/unixtime.aspx根据上面的时间获取的,这个问题模拟器和真机都存在。我没有找到原因,个人猜想,应该是闰年、平年的原因,因为1985年2月只有28天,2016年2月有29天,如果读者你知道原因,麻烦告诉我,thx。
    参考链接

    # S! T9 \4 r9 ~  I- k

    - f9 u1 v8 ^  V; x+ N5 B
    使用道具 举报 回复
    严禁恶意灌水!!!拒绝伸手党!!!
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    ض