DateFormatter使用不正确的时区格式化字符串

时间:2018-08-14 14:52:58

标签: ios swift datetime

前提条件

在手机设置中设置时区GMT + 13(Fale,Tokeleau)。

实施

extension Date {
    func formatForDto() -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZ"
        return dateFormatter.string(from: self)
    }
}

示例

let date = Date(timeIntervalSince1970: 320756400) // which is 1980-03-01 11:00:00 UTC
let result = date.formatForDto()

结果

result = "1980-03-01 00:00:00 -1100"而不是1980-03-02 00:00:00 +1300(11:00 + 13)。

在调试器中,当我检查dateFormatter.timeZone的内容时,会得到正确的结果:

(lldb) po dateFormatter.timeZone
▿ Optional<TimeZone>
  ▿ some : Pacific/Fakaofo (current)
    - identifier : "Pacific/Fakaofo"
    - kind : "current"
    ▿ abbreviation : Optional<String>
      - some : "GMT+13"
    - secondsFromGMT : 46800
    - isDaylightSavingTime : false

预期结果

根据documentation

  

DateFormatter.timeZone-如果未指定,则使用系统时区。

我的函数应该返回1980-03-02 00:00:00 +1300

解决方法

更有意思的是,当我手动将timeZone设置为:

dateFormatter.timeZone = TimeZone(secondsFromGMT: 13 * 60 * 60)

然后它会按预期返回1980-03-02 00:00:00 +1300

问题

那么,为什么不设置timeZone却不能按照文档中的要求工作,并且不考虑系统的时区呢?是SDK中的错误吗?

1 个答案:

答案 0 :(得分:0)

这个问题非常有趣,因为事实证明它是由时区引起的:Fale, Tokeleau我认为是 GMT + 13 ,但是根据Time Zone in Fakaofo, Tokelau,此时区之前2011年12月30日是 GMT-11

这就是为什么在我的示例1980-03-01 11:00:00 UTC中应用了不同的偏移量的原因,这就是为什么它与TimeZone(secondsFromGMT: 13 * 60 * 60)一起使用的原因,它指定了确切的偏移量而不是时区。

因此,如果我用日期检查代码:

  • 2012-03-01 11:00:00 UTC返回1980-03-02 00:00:00 +1300
  • 1980-03-01 11:00:00 UTC返回1980-03-01 00:00:00 -1100