80年代的第一个日期未能在iOS 10.0中解析

sup*_*p-f 5 foundation nsdateformatter ios swift

我发现DateFormatter date(from:)方法无法解析几个特定的​​日期.方法返回nil1981年至1984年的第一个月.这是基金会的错误吗?我们可以做些什么来解析这些日期?

Xcode 8.0,iOS SDK 10.0.这是一个简短的游乐场示例的屏幕截图: 一个简短的游乐场示例的屏幕截图

Mar*_*n R 18

如果夏令时恰好在午夜开始, 就会发生这个问题,就像1981 - 1984年莫斯科的情况一样(例如参见俄罗斯莫斯科的时钟变化(莫斯科)).

这也是在观察到的

例如,在1984年4月1日午夜,时钟向前调整一小时,这意味着该时区中不存在"1984-04-01 00:00"日期:

let dFmt = DateFormatter()
dFmt.dateFormat = "yyyy-MM-dd"
dFmt.timeZone = TimeZone(identifier: "Europe/Moscow")
print(dFmt.date(from: "1984-04-01")) // nil
Run Code Online (Sandbox Code Playgroud)

作为解决方案,您可以告诉日期格式化程序"宽松":

dFmt.isLenient = true
Run Code Online (Sandbox Code Playgroud)

然后它将返回当天的第一个有效日期:

dFmt.isLenient = true
if let date = dFmt.date(from: "1984-04-01") {
    dFmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
    print(dFmt.string(from: date)) 
}
// 1984-04-01 01:00:00
Run Code Online (Sandbox Code Playgroud)

rob mayoff给出了一个不同的解决方案,即使日期格式化程序使用正午而不是午夜作为默认日期.这是从Objective-C到Swift的rob代码的翻译:

let noon = DateComponents(calendar: dFmt.calendar, timeZone: dFmt.timeZone,
               year: 2001, month: 1, day: 1, hour: 12, minute: 0, second: 0)
dFmt.defaultDate = noon.date
if let date = dFmt.date(from: "1984-04-01") {
    dFmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
    print(dFmt.string(from: date)) 
}
// 1984-04-01 12:00:00
Run Code Online (Sandbox Code Playgroud)