【问题标题】:How do I make JSONDecoder parse this format? (yyyy-MM-dd'T'HH:mm:ss.SSSSSSS)如何让 JSONDecoder 解析这种格式? (yyyy-MM-dd'T'HH:mm:ss.SSSSSSS)
【发布时间】:2017-11-28 14:14:31
【问题描述】:

这就是我要解码的内容:

{"MessageDate":"2017-11-28T05:04:40.9611765"}

我省略了 JSON 结构的其余部分。

我如何让JSONDecoder 将该日期格式解析为Date 对象?

这是我迄今为止尝试过的:

extension Formatter
{
    static let dotNetDateTime: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
        return formatter
    }()

    /// https://stackoverflow.com/a/46458771/8462094
    static let dotNetDateTimeISO8601: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
        return formatter
    }()

    /// https://stackoverflow.com/a/46458771/8462094
    static let dotNetDateTimeISO8601NoMS: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
        return formatter
    }()

    static let dotNetDateTimeCustom: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSS"
        return formatter
    }()

    static let iso8601Full: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXX"
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        return formatter
    }()
}

其中一些来自其他 Stack Overflow 帖子。
我还尝试了很多上面未列出的其他日期解码策略。
我已经在互联网上搜索了几个小时以寻找解决方案。
我看过Unicode documentation for date format patterns
我求助了另一个朋友,他也不知道。

我怀疑日期字符串末尾的七位浮点数是罪魁祸首,但我不知道如何解决。
也许我只是错过了一些非常小的东西。再来一双眼睛就好了。

非常感谢任何帮助,谢谢。

我想我应该包含我正在解析的实际代码:

let attempt1 = JSONDecoder()
attempt1.dateDecodingStrategy = .formatted(Formatter.dotNetDateTime)
let attempt2 = JSONDecoder()
attempt2.dateDecodingStrategy = .formatted(Formatter.dotNetDateTimeISO8601)
//And more attempt initializations
...
print(String(data: data, encoding: .utf8)!)
if let deser = try? attempt1.decode(MessageThreads.self, from: data)
{
    return onDone(deser, nil)
}
if let deser = try? attempt2.decode(MessageThreads.self, from: data)
{
    return onDone(deser, nil)
}
//And more attempts
...

【问题讨论】:

    标签: json swift datetime swift4


    【解决方案1】:

    知道了。有时当您需要调试时,请使用 Playgrounds。

    extension Formatter
    {
        static let dotNetDateTimeWithMilliseconds: DateFormatter = {
            let formatter = DateFormatter()
            formatter.locale = Locale(identifier: "en_US_POSIX")
            formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.S"
            return formatter
        }()
    }
    

    只需一个.S 即可解析它。

    编辑:
    @Leo Dabus 说我应该包含语言环境,所以我添加了它。感谢 Leo 的帮助!

    【讨论】:

    • 确保将您的语言环境设置为 en_US_POSIX。另一件事是您确定来自服务器的日期字符串不是UTC时间吗?
    • 顺便说一句,这也会在解析日期时丢弃剩余的小数秒。如果您是构建 API 的人,最好使用双精度并在您的 json 中传递 timeIntervalSinceReferenceDate
    • 我不太明白en_US_POSIX 的作用。我知道它会强制将语言环境设置为美国,但这究竟意味着什么?如果我知道服务器位于美国,我是否要强制使用区域设置?如果服务器在欧洲或其他地方怎么办,我是否必须使用不同的语言环境?此外,如果我继续添加像.SSSSSSS 这样的 S,其余的小数秒仍然会被丢弃。 (我不是在构建 API(但我真的希望 api 使用自 UNIX 或其他东西以来的毫秒数))
    • 服务器的位置无关紧要。 en_US_POSIX 需要正确解析您的字符串
    • 解析日期时的最大小数秒数为 3。其余的将被忽略
    猜你喜欢
    • 1970-01-01
    • 2019-11-09
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-28
    • 1970-01-01
    相关资源
    最近更新 更多