Xcode 11 破坏了 DateFormatter?

Xcode 11 broke DateFormatter?

有一天,应用程序成功了。第二天,我更新到 Xcode 11,现在应用程序崩溃并显示图片中第 27 行(执行第 15 行时)的 "unexpectedly found nil"。

我问了我的同事,他还没有 Xcode 11,他没有崩溃。我们在同一个 branch/commit...一切。

有什么建议吗?有什么办法解决这个问题吗?

我的代码:

// ticket.timeOrdered == "2019-10-03 22:54:57 +0000"

let ticketDate = ticket.timeOrdered.asCrazyDate.timeIntervalSince1970

extension String {

    var asCrazyDate: Date {
        let dateFormatterGet = DateFormatter()
        dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss +zzzz"
        dateFormatterGet.timeZone = .current
        return dateFormatterGet.date(from: self)!
    }
}

日期格式字符串不正确。 +zzzz 不是 acceptable 格式。请参阅 Date Format Patterns 中 table 的时区相关部分。 + 不应该在那里。 zzzz 用于时区的详细描述(例如“太平洋夏令时”)。您可以通过使用相同的格式化程序从 Date() 构建字符串来验证这一点,您会发现它不会像您预期的那样产生 +0000

最新 SDK 的日期格式化程序不再像以前的版本那样对这些格式字符串错误宽容。但是,与其还原 Xcode 版本,不如修复该日期格式字符串。例如,您可以使用 Z 而不是 +zzzz,这将正确地将 +0000(或其他)解释为字符串的时区部分。


其他一些建议,如果您不介意的话:

  1. 本例中不需要asCrazyDate。获取日期、使用字符串插值来构建字符串表示,然后使用格式化程序将字符串转换回日期(您最初使用的日期)是没有意义的。你可以直接使用 Date:

    func getDate() -> TimeInterval {
        return Date().timeIntervalSince1970
    }
    
  2. 众所周知,创建日期格式化程序需要大量计算,如果您经常使用此计算 属性,那确实会影响性能。如果可能,最好实例化一次日期格式化程序。

  3. 如果你出于某种原因试图构建一些不变的日期字符串,最好使用类似 ISO8601DateFormatter 的东西。所以不要使用字符串插值来构建日期字符串,也不要构建自己的格式化程序。

    let formatter = ISO8601DateFormatter()
    
    let now = Date()
    let string = formatter.string(from: now) // not "\(now)"
    
    let date = formatter.date(from: string)
    
    print(now, string, date)
    
  4. 如果您受困于这种日期格式(也许您已经使用这种字符串格式存储日期),如果必须的话,您可以使用自定义 dateFormat 字符串。但正如 Technical Q&A 1480 所建议的那样,您可能想要设置 locale(我建议也设置 timeZone,以便您的日期字符串具有可比性)。

    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.timeZone = TimeZone(secondsFromGMT: 0)