【问题标题】:1st april dates of 80s failed to parse in iOS 10.080 年代的 4 月 1 日日期在 iOS 10.0 中无法解析
【发布时间】:2017-03-10 02:49:55
【问题描述】:

我发现 DateFormatter date(from:) 方法无法解析几个特定日期。方法返回 1981-1984 年 4 月 1 日的 nil。是基金会的bug吗?我们可以做些什么来解析这些日期?

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

【问题讨论】:

  • 你在哪个时区?夏令时是从那天开始的吗?
  • 不是Foundation的bug。我可以得到这些日期的正确值。这似乎是一个不起作用的特定配置(时区、公历......)。我正在伦敦进行测试。
  • 不,这不是 Foundation 的错误。尝试更改时区和日历。它应该可以解决您的问题。
  • @MartinR 你是对的。这一天的夏令时仅从那 4 年开始。时区:欧洲/莫斯科。如何在不更改日历或时区的情况下解析此类日期?

标签: ios swift nsdateformatter foundation


【解决方案1】:

如果夏令时正好在 午夜,就像 1981 年至 1984 年间莫斯科的情况一样(例如,参见 Clock Changes in Moscow, Russia (Moskva))。

这在

中也观察到了

例如,在 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

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

dFmt.isLenient = true

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

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

A different solution 由 rob mayoff 给出,这是为了让日期格式化程序使用 noon 而不是午夜作为 默认日期。这是 rob 的代码从 Objective-C 到 Swift 的翻译:

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

【讨论】:

  • defaultDate 技巧很高兴知道。 (已投票)关于该属性的文档几乎毫无价值。你是怎么知道它的作用的?
  • @DuncanC:实际上我猜测 isLenient 属性(记录更少)在这里有帮助。 defaultDate 解决方案只是将链接到 Objective-C 的代码翻译成 Swift,这是由 Rob Mayoff 发现的。
猜你喜欢
  • 2022-10-14
  • 2021-07-05
  • 1970-01-01
  • 1970-01-01
  • 2020-06-18
  • 2012-02-13
  • 2015-07-01
  • 2018-08-09
  • 1970-01-01
相关资源
最近更新 更多