如何在 Swift 5 中将 `Date` 转换为 `Data`,反之亦然?

How to convert `Date` to `Data`, and vice versa in Swift 5?

我正在尝试在钥匙串中保存日期,并且(根据我的理解)这首先需要将 Date 对象转换为 Data 对象。

在 Swift 3 中解释了如何做(或至少部分),但我希望有人可以在 [=19] 中提供 to/from 功能=] 5(因为该解决方案中至少有一种方法已被弃用,我担心其他方法也没有经受住时间的考验)。

A Date 是一个时间戳(自 1970 年 UTC 参考日期以来的秒数)作为具有奇特方法和其他实用程序的对象。仅此而已。

所以基于 Double to Data (and reverse):

输入

let date = Date()
print(date)

日期 -> 时间戳 -> 数据

let timestamp = date.timeIntervalSinceReferenceDate
print(timestamp)
let data = withUnsafeBytes(of: timestamp) { Data([=11=]) }
print("\(data) - \(data.map{ String(format: "%02hhx", [=11=]) }.joined())")

数据 -> 时间戳 -> 日期

let retrievedTimestamp = data.withUnsafeBytes { [=12=].load(as: Double.self) }
print(retrievedTimestamp)
let retrievedDate = Date(timeIntervalSinceReferenceDate: retrievedTimestamp)
print(retrievedDate)

输出:

$>2021-09-13 08:17:50 +0000
$>1631521070.6852288
$>8 bytes - cadaab4bc24fd841
$>1631521070.6852288
$>2021-09-13 08:17:50 +0000

一种“更安全”(但效率较低)的方法是使用 Encoder/Decoder 类型,例如 Foundations JSONEncoder/ JSONDecoder。 如果数据以某种方式损坏,这些类型将抛出 Error,而不是陷阱。 您只需要确保每个日期 encoding/decoding 策略都相同。

let myDate = Date()

let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .secondsSince1970
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970

// TODO: handle errors correctly
let dateData = try! encoder.encode(myDate)
let retrievedDate = try! decoder.decode(Date.self, from: dateData)

assert(myDate == retrievedDate)