This question already has answers here:
How to convert a date string with optional fractional seconds using Codable in Swift4

(4 个回答)


2年前关闭。




我有以下代码来解析 ISO8601 日期。
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"

问题是有时日期的格式类似于 2018-01-21T20:11:20.057Z ,有时它的格式类似于 2018-01-21T20:11:20Z

所以基本上部分时间它有 .SSS 毫秒部分,而其他时候它没有。

如何设置日期格式化程序以使该部分可选?

编辑

我忘了在我刚刚意识到的问题中提及一些细节。所以我在 Swift 4 中使用了 JSON Codable 功能。所以如果它失败,它只会抛出一个错误。

所以我基本上有以下代码。
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(isoMilisecondDateFormatter())

return try decoder.decode([Person].self, from: _people)
_people 的示例 JSON 对象如下。
[
    {
        "name": "Bob",
        "born": "2018-01-21T20:11:20.057Z"
    },
    {
        "name": "Matt",
        "born": "2018-01-21T20:11:20Z"
    }
]

我正在使用的 API 非常不一致,所以我必须处理多种类型的数据。

最佳答案

两个建议:

  • 将字符串转换为包含毫秒的日期格式。如果它返回 nil 将其转换为其他格式。
  • 使用正则表达式从字符串中去除毫秒数:
    var dateString = "2018-01-21T20:11:20.057Z"
    dateString = dateString.replacingOccurrences(of: "\\.\\d+", with: "", options: .regularExpression)
    // -> 2018-01-21T20:11:20Z
    

  • 编辑:

    要将它与 Codable 一起使用,您必须编写自定义初始值设定项,指定 dateDecodingStrategy 不起作用
    struct Foo: Decodable {
        let birthDate : Date
        let name : String
    
        private enum CodingKeys : String, CodingKey { case born, name }
    
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            var rawDate = try container.decode(String.self, forKey: .born)
            rawDate = rawDate.replacingOccurrences(of: "\\.\\d+", with: "", options: .regularExpression)
            birthDate = ISO8601DateFormatter().date(from: rawDate)!
            name = try container.decode(String.self, forKey: .name)
        }
    }
    
    let jsonString = """
    [{"name": "Bob", "born": "2018-01-21T20:11:20.057Z"}, {"name": "Matt", "born": "2018-01-21T20:11:20Z"}]
    """
    
    do {
        let data = Data(jsonString.utf8)
        let result = try JSONDecoder().decode([Foo].self, from: data)
        print(result)
    } catch {
        print("error: ", error)
    }
    

    关于ios - Swift DateFormatter 可选的毫秒数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48371082/

    10-14 21:51