date - 如何在 Swift 中解析/创建格式为小数秒 UTC 时区(ISO 8601、RFC 3339)的日期时间戳?

标签 date swift time iso8601 rfc3339

如何使用 ISO 8601 的格式标准生成日期时间戳记和 RFC 3339

目标是一个如下所示的字符串:

"2015-01-01T00:00:00.000Z"

格式:

  • 年、月、日,如“XXXX-XX-XX”
  • 字母“T”作为分隔符
  • 时、分、秒、毫秒,如“XX:XX:XX.XXX”。
  • 字母“Z”作为零偏移的区域指示符,又称 UTC、GMT、Zulu 时间。

最好的情况:

  • Swift 源代码简单、简短、直接。
  • 无需使用任何额外的框架、子项目、cocoapod、C 代码等。

我搜索了 StackOverflow、Google、Apple 等,但没有找到对此问题的 Swift 答案。

看起来最有前途的类是 NSDate , NSDateFormatter , NSTimeZone .

相关问答:How do I get an ISO 8601 date on iOS?

这是迄今为止我想到的最好的:

var now = NSDate()
var formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
println(formatter.stringFromDate(now))

最佳答案

Swift 4 • iOS 11.2.1 或更高版本

extension ISO8601DateFormatter {
    convenience init(_ formatOptions: Options) {
        self.init()
        self.formatOptions = formatOptions
    }
}
<小时/>
extension Formatter {
    static let iso8601withFractionalSeconds = ISO8601DateFormatter([.withInternetDateTime, .withFractionalSeconds])
}
<小时/>
extension Date {
    var iso8601withFractionalSeconds: String { return Formatter.iso8601withFractionalSeconds.string(from: self) }
}
<小时/>
extension String {
    var iso8601withFractionalSeconds: Date? { return Formatter.iso8601withFractionalSeconds.date(from: self) }
}
<小时/>

用法:

Date().description(with: .current)  //  Tuesday, February 5, 2019 at 10:35:01 PM Brasilia Summer Time"
let dateString = Date().iso8601withFractionalSeconds   //  "2019-02-06T00:35:01.746Z"

if let date = dateString.iso8601withFractionalSeconds {
    date.description(with: .current) // "Tuesday, February 5, 2019 at 10:35:01 PM Brasilia Summer Time"
    print(date.iso8601withFractionalSeconds)           //  "2019-02-06T00:35:01.746Z\n"
}
<小时/>

iOS 9 • Swift 3 或更高版本

extension Formatter {
    static let iso8601withFractionalSeconds: 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
    }()
}
<小时/>

Codable Protocol

If you need to encode and decode this format when working with Codable protocol you can create your own custom date encoding/decoding strategies:

extension JSONDecoder.DateDecodingStrategy {
    static let iso8601withFractionalSeconds = custom {
        let container = try $0.singleValueContainer()
        let string = try container.decode(String.self)
        guard let date = Formatter.iso8601withFractionalSeconds.date(from: string) else {
            throw DecodingError.dataCorruptedError(in: container,
                  debugDescription: "Invalid date: " + string)
        }
        return date
    }
}

以及编码策略

extension JSONEncoder.DateEncodingStrategy {
    static let iso8601withFractionalSeconds = custom {
        var container = $1.singleValueContainer()
        try container.encode(Formatter.iso8601withFractionalSeconds.string(from: $0))
    }
}
<小时/>

Playground 测试

let dates = [Date()]   // ["Feb 8, 2019 at 9:48 PM"]

编码

let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601withFractionalSeconds
let data = try! encoder.encode(dates)
print(String(data: data, encoding: .utf8)!)

解码

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601withFractionalSeconds
let decodedDates = try! decoder.decode([Date].self, from: data)  // ["Feb 8, 2019 at 9:48 PM"]

enter image description here

关于date - 如何在 Swift 中解析/创建格式为小数秒 UTC 时区(ISO 8601、RFC 3339)的日期时间戳?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47181686/

相关文章:

ios - 无法弄清楚如何使用 CLPlacemark 将我的当前位置正确地嵌入到消息正文中

ios - 错误处理 - 错误传播

iphone - 使用堆栈的导航 Controller / View Controller

android - 如何防止用户设置早于当前日期和时间的日期和时间

mysql - 使用时间戳和计数格式化 MySQL 查询

javascript - 为什么日期没有正确生成?

java - 日期排序 - 从最新到最旧

java - 如何跟踪系统时钟

python - 为什么我在 matplotlib 的 x 轴上得到垃圾日期值?

python - 获取明天日期的最简洁和最 Pythonic 的方式?