如何在 Swift 中解析/创建格式化为 UTC 时区(ISO 8601、RFC 3339)的小数秒格式的日期时间戳? [英] How can I parse / create a date time stamp formatted with fractional seconds UTC timezone (ISO 8601, RFC 3339) in Swift?

查看:132
本文介绍了如何在 Swift 中解析/创建格式化为 UTC 时区(ISO 8601、RFC 3339)的小数秒格式的日期时间戳?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用ISO 8601和<的格式标准生成日期时间戳a href="https://www.rfc-editor.org/rfc/rfc3339" rel="nofollow noreferrer">RFC 3339?

目标是一个看起来像这样的字符串:

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

格式:

  • 年、月、日,如XXXX-XX-XX"
  • 字母T"作为分隔符
  • 时、分、秒、毫秒,如XX:XX:XX.XXX".
  • 字母Z"作为零偏移的区域指示符,也就是 UTC、GMT、祖鲁时间.

最佳情况:

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

我搜索了 StackOverflow、Google、Apple 等,但没有找到 Swift 的答案.

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

相关问答:如何获取 ISOiOS 上的 8601 日期?

这是我目前想到的最好的:

var now = NSDate()var 格式化程序 = 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 或更高版本

扩展 ISO8601DateFormatter {方便初始化(_格式选项:选项){self.init()self.formatOptions = formatOptions}}


extension Formatter {静态 let iso8601withFractionalSeconds = ISO8601DateFormatter([.withInternetDateTime, .withFractionalSeconds])}


延期日期{var iso8601withFractionalSeconds: String { return Formatter.iso8601withFractionalSeconds.string(from: self) }}


扩展字符串{var iso8601withFractionalSeconds:日期?{ 返回 Formatter.iso8601withFractionalSeconds.date(from: self) }}


用法:

Date().description(with: .current)//2019 年 2 月 5 日,星期二,巴西利亚夏令时间晚上 10:35:01"let dateString = Date().iso8601withFractionalSeconds//2019-02-06T00:35:01.746Z"如果让日期 = dateString.iso8601withFractionalSeconds {date.description(with: .current)//巴西利亚夏令时间,2019 年 2 月 5 日星期二晚上 10:35:01"打印(date.iso8601withFractionalSeconds)//2019-02-06T00:35:01.746Z
"}


iOS 9 • Swift 3 或更高版本

extension Formatter {静态 let iso8601withFractionalSeconds: DateFormatter = {让格式化程序 = DateFormatter()formatter.calendar = 日历(标识符:.iso8601)formatter.locale = Locale(标识符:en_US_POSIX")formatter.timeZone = TimeZone(secondsFromGMT: 0)formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX";返回格式化程序}()}


<块引用>

可编码协议

如果在使用 Codable 时需要对这种格式进行编码和解码协议,您可以创建自己的自定义日期编码/解码策略:

extension JSONDecoder.DateDecodingStrategy {静态让 iso8601withFractionalSeconds = 自定义 {让容器 = 尝试 $0.singleValueContainer()让字符串 = 尝试 container.decode(String.self)守卫让日期 = Formatter.iso8601withFractionalSeconds.date(from: string) else {抛出 DecodingError.dataCorruptedError(in: 容器,调试说明:无效日期:"+ 字符串)}归期}}

和编码策略

extension JSONEncoder.DateEncodingStrategy {静态让 iso8601withFractionalSeconds = 自定义 {var 容器 = $1.singleValueContainer()试试 container.encode(Formatter.iso8601withFractionalSeconds.string(from: $0))}}


游乐场测试

let dates = [Date()]//[2019 年 2 月 8 日晚上 9:48"]

编码

让编码器 = JSONEncoder()编码器.dateEncodingStrategy = .iso8601withFractionalSeconds让数据=尝试!编码器.编码(日期)打印(字符串(数据:数据,编码:.utf8)!)

解码

让解码器 = JSONDecoder()解码器.dateDecodingStrategy = .iso8601withFractionalSeconds让decodedDates = 试试!decoder.decode([Date].self, from: data)//[2019 年 2 月 8 日晚上 9:48"]

How to generate a date time stamp, using the format standards for ISO 8601 and RFC 3339?

The goal is a string that looks like this:

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

Format:

  • year, month, day, as "XXXX-XX-XX"
  • the letter "T" as a separator
  • hour, minute, seconds, milliseconds, as "XX:XX:XX.XXX".
  • the letter "Z" as a zone designator for zero offset, a.k.a. UTC, GMT, Zulu time.

Best case:

  • Swift source code that is simple, short, and straightforward.
  • No need to use any additional framework, subproject, cocoapod, C code, etc.

I've searched StackOverflow, Google, Apple, etc. and haven't found a Swift answer to this.

The classes that seem most promising are NSDate, NSDateFormatter, NSTimeZone.

Related Q&A: How do I get an ISO 8601 date on iOS?

Here's the best I've come up with so far:

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 or later

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) }
}


Usage:

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
"
}


iOS 9 • Swift 3 or later

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
    }
}

and the encoding strategy

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


Playground Testing

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

encoding

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

decoding

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

这篇关于如何在 Swift 中解析/创建格式化为 UTC 时区(ISO 8601、RFC 3339)的小数秒格式的日期时间戳?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆