谁正在以正确的方式实施ISO8601?斯威夫特还是春天?

问题描述 投票:0回答:2

Spring框架中使用的Jackson序列化程序的默认行为如下:(来自spring-data-rest源代码):

        /**
         * The most common ISO DateTime Format {@code yyyy-MM-dd'T'HH:mm:ss.SSSZ},
         * e.g. "2000-10-31T01:30:00.000-05:00".
         * <p>This is the default if no annotation value is specified.
         */

所以这种格式化的一个例子可能是2019-03-20T11:18:46.000+0000。 Swift也有ISO8601解码器,但事实上,对于Swift来说,这个字符串由于毫秒而只有无效的格式。如果删除毫秒部分,swift可以成功反序列化字符串。

struct Test: Codable {
    let createdAt: Date
}

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

let data2 = "{\"createdAt\": \"2018-12-05T14:05:35.000+0000\"}".data(using: .utf8)!
let decoded2 = try! decoder.decode(Test.self, from: data2)

Swift指的是RFC 3339 https://www.ietf.org/rfc/rfc3339.txt,并没有提到毫秒。我的问题是 - 什么格式是正确的呢?如果某些东西是ISO格式的,应该严格定义,我通常不希望编写自定义反序列化器(swift)或定义序列化的自定义模式(spring)。

swift spring iso
2个回答
1
投票

您应该设置iso8601选项。您可以使用ISO8601DateFormatter来完成。

struct Test: Codable {
    let createdAt: Date
}

enum CustomDateDecodingStrategy {

    private static let formatter: ISO8601DateFormatter = {
        let formatter = ISO8601DateFormatter()
        formatter.formatOptions = [
            .withFullDate,
            .withFullTime,
            .withTimeZone,
            .withFractionalSeconds
        ]
        return formatter
    }()

    static func decode(_ decoder: Decoder) throws -> Date {
        let container = try decoder.singleValueContainer()
        let dateStr = try container.decode(String.self)
        if let date = formatter.date(from: dateStr) {
            return date
        } else {
            throw NSError(domain: "date", code: -1, userInfo: nil)
        }
    }

}

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom(CustomDateDecodingStrategy.decode)

let data2 = "{\"createdAt\": \"2018-12-05T14:05:35.000+0000\"}".data(using: .utf8)!
let decoded2 = try! decoder.decode(Test.self, from: data2)

1
投票

第23页the ISO8601 2016 draft

如果特定应用需要,可以包括小时,分钟或秒的小数部分。如果包含小数部分,则应省略低阶时间元素(如果有),小数部分应从整数部分除以ISO 31-0中指定的小数符号,即逗号[,]或句号[ ]。其中,逗号是首选标志。如果数字的大小小于1,则小数符号前面应按照3.6的两个零。

所以2018-12-05T14:05:35.000是合法的。虽然RFC 3339没有按名称提及毫秒,但它确实谈到了“分数”,例如:

下面定义的格式仅包括一个很少使用的选项:一秒的分数。预计这将仅用于需要严格订购日期/时间戳或具有不寻常精度要求的应用程序。

ISO 8601还要求(在第5.3.1.3节中)如果小于1,则小数部分前进为“0”。 ISO 8601的附录B.2给出了小数分数前面没有“0”的例子。该语法假设第5.3.1.3节是正确的,附件B.2是错误的。

© www.soinside.com 2019 - 2024. All rights reserved.