最新消息:iOS编程开发交流群(6906921) ,Mac.Cocoa开发交流群(7758675) 欢迎iOS/macOS开发编程爱好及学习者加入!

iOS开发之夏令时,NSDateFormatter格式化失败

iOS 天狐 20486浏览 2评论

起因:最近有需求要把  1988-04-10类似的时间字符串使用NSDateFormatter转化成时间戳或者NSDate

现象:测试发现iOS格式化某些特殊时间字符串到NSDate的时候会后会返回空值,比如 1988-04-10,1989-04-16,1989-04-16 12:12等等时间

当NSDateFormatter没有指定TimeZone的时候,在中国设备上一般默认都是Asia/Shanghai时区

查阅资料发现是夏令时问题

夏令时问题

1986年4月,我国采取夏令时,具体作法是:每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时,即将表针由2时拨至3时,夏令时开始;到九月中旬第一个星期日的凌晨2时整(北京夏令时),再将时钟拨回一小时,即将表针由2时拨至1时,夏令时结束。从1986年到1991年的六个年度,除1986年因是实行夏时制的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。在夏令时开始和结束前几天,新闻媒体均刊登有关部门的通告。1992年起,夏令时暂停实行。
关于夏令时的详细资料
中国夏时制实施时间规定(夏令时)
1935年至1951年,每年5月1日至9月30日。
1952年3月1日至10月31日。
1953年至1954年,每年4月1日至10月31日。
1955年至1956年,每年5月1日至9月30日。
1957年至1959年,每年4月1日至9月30日。
1960年至1961年,每年6月1日至9月30日。
1974年至1975年,每年4月1日至10月31日。
1979年7月1日至9月30日。
1986年至1991年,每年4月中旬的第一个星期日1时起至9月中旬的第一个星期日1时止。具体如下:
1986年4月13日至9月14日,
1987年4月12日至9月13日,
1988年4月10日至9月11日,
1989年4月16日至9月17日,
1990年4月15日至9月16日,
1991年4月14日至9月15日。

以上所有日期时间格式化时候都会出现空值问题

使用Asia/Shanghai TimeZone 就会出现问题

而使用GMT市区 问题消失

[_dateForrmatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];

那么问题来了.....app中之前的所有时间都是用的Asia/Shanghai市区,又不可能直接使用GMT时区替换...磕了 寻找解决方案

解决办法

为了把更改量降到最低

使用 [NSTimeZone timeZoneForSecondsFromGMT:3600*8]; 设置时区

不要使用[NSTimeZone timeZoneWithName:@"Asia/Shanghai"]

虽然理论上shanghai是比GMT多了8个时区,但是结果是不一样的....

多个国家切换问题

使用 [NSTimeZone timeZoneForSecondsFromGMT:3600*8]; 设置时区,的确可以解决大陆的夏令时时间问题.

如果APP需要多个时区使用那么写死3600*8就不那么完美了.

我们都知道3600*8是目标时区与GMT时区相差的秒数而已,那么动态计算出来这个Offset秒数即可.

问题完美解决

 

写了一个NSTimeZone的Category
https://github.com/shaojiankui/NSTimeZone-JKLocalTimeZone

转载请注明:天狐博客 » iOS开发之夏令时,NSDateFormatter格式化失败

微信 OR 支付宝 扫描二维码
为天狐 打赏
非常感谢你的支持,哥会继续努力!
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (2)

  1. 恩,谢谢详细的解释,原来是历史遗留问题。另外,这种解决方法不太好吧,如果是国外用户,那时间就不对了,应该如何兼容的解决呢?
    小飞8年前 (2016-07-19)回复
    • 额 这的确是一个问题。。。。[[NSTimeZone localTimeZone] secondsFromGMTForDate:[NSDate date]
      天狐8年前 (2016-07-19)回复