首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用swift4解码iso8601 date json

使用swift4解码iso8601 date json
EN

Stack Overflow用户
提问于 2017-10-03 13:35:34
回答 2查看 13K关注 0票数 26

所以,我的json中有类似于"2016-06-07T17:20:00.000+02:00“的iso8601日期。

有没有办法使用swift4解析这些iso8601日期?我是不是漏掉了什么明显的东西?

我尝试了以下方法,但只有来自jsonShipA的dateString "2016-06-07T17:20:00Z“是可解析的……

代码语言:javascript
复制
import Foundation

struct Spaceship : Codable {
    var name: String
    var createdAt: Date
}

let jsonShipA = """
{
    "name": "Skyhopper",
    "createdAt": "2016-06-07T17:20:00Z"
}
"""

let jsonShipB = """
{
    "name": "Skyhopper",
    "createdAt": "2016-06-07T17:20:00.000+02:00"
}
"""

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601

let dataA = jsonShipA.data(using: .utf8)!
if let decodedShip = try? decoder.decode(Spaceship.self, from: dataA) {
    print("jsonShipA date = \(decodedShip.createdAt)")
} else {
    print("Failed to decode iso8601 date format from jsonShipA")
}

let dataB = jsonShipB.data(using: .utf8)!
if let decodedShip = try? decoder.decode(Spaceship.self, from: dataB) {
    print("jsonShipA date = \(decodedShip.createdAt)")
} else {
    print("Failed to decode iso8601 date format from jsonShipB")
}

游乐场的输出为:

代码语言:javascript
复制
jsonShipA date = 2016-06-07 17:20:00 +0000
Failed to decode iso8601 date format from jsonShipB

抛出的错误是“期望日期字符串采用ISO8601格式”。但据我所知,日期"2016-06-07T17:20:00.000+02:00“是一个有效的ISO8601日期

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-03 14:51:02

您可以像这样使用:

代码语言:javascript
复制
enum DateError: String, Error {
    case invalidDate
}

let decoder = JSONDecoder() 

let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)

decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
    let container = try decoder.singleValueContainer()
    let dateStr = try container.decode(String.self)

    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
    if let date = formatter.date(from: dateStr) {
        return date
    }
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
    if let date = formatter.date(from: dateStr) {
        return date
    }
    throw DateError.invalidDate
})
票数 49
EN

Stack Overflow用户

发布于 2017-10-03 14:33:03

TL;DR版本:只解析ISO8601DateFormatter described here的withInternetDateTime格式。这意味着你的字符串不应该有毫秒。

更多信息:

看看第787行的the Swift source,评论是这样说的:

代码语言:javascript
复制
/// Decode the `Date` as an ISO-8601-formatted string (in RFC 3339 format).

看一下这个RFC,它在5.8节中给出了几个例子(诚然很棘手):

代码语言:javascript
复制
1985-04-12T23:20:50.52Z
1996-12-19T16:39:57-08:00
1996-12-20T00:39:57Z
1990-12-31T23:59:60Z
1990-12-31T15:59:60-08:00
1937-01-01T12:00:27.87+00:20

只有第二个和第三个示例实际上被Swift解码了,其余的都失败了。在我看来,要么是注释不正确,要么是实现不完整。至于真正的实现,那是在Swift源代码之外,它似乎只是使用了基础中的ISO8601DateFormatter类。

Swift unittest也非常有限,请参见第180行。它只是简单地对单个日期进行编码,然后再将其解码。换句话说,唯一要测试的就是ISO8601DateFormatter默认输出的格式,它被硬编码到选项.withInternetDateTimedescribed here中。

票数 43
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46537790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档