将网络中的日期(绝对时间)转换为 sent/received 作为 Swift 中的数据?
Convert a Date (absolute time) to be sent/received across the network as Data in Swift?
我正在寻找一种 Swifty 方法来生成时间戳。
我的 macOS 应用程序记录了一些数据并在其上标记了创建数据的时间。然后数据将通过网络发送(如 Data
)以在 iPad.
上重建
是否有任何 Swift class 可以生成时间戳? NSDate? NSTimeIntervalSince1970? CFAbsoluteTimeGetCurrent()
要求是:
- 以尽可能少的字节存储时间戳(pref.
Int
)
- 与真实地球时间有些相似(我宁愿不生成我的
自己的时间格式)
- 毫秒精度
- 构建速度快
- iOS 9+, macOS 10.10+
使用TimeIntervalSince1970
类型:
let exactTimeInMilliseconds = Date().timeIntervalSince1970
原来的回答效率很低。
您可以发送 Date
将其转换为 Data
(8 字节浮点数)并返回 Date
,如下所示:
extension Numeric {
var data: Data {
var source = self
return .init(bytes: &source, count: MemoryLayout<Self>.size)
}
init<D: DataProtocol>(_ data: D) {
var value: Self = .zero
let size = withUnsafeMutableBytes(of: &value, { data.copyBytes(to: [=10=])} )
assert(size == MemoryLayout.size(ofValue: value))
self = value
}
}
extension UInt64 {
var bitPattern: Double { .init(bitPattern: self) }
}
extension Date {
var data: Data { timeIntervalSinceReferenceDate.bitPattern.littleEndian.data }
init<D: DataProtocol>(data: D) {
self.init(timeIntervalSinceReferenceDate: data.timeIntervalSinceReferenceDate)
}
}
extension DataProtocol {
func value<N: Numeric>() -> N { .init(self) }
var uint64: UInt64 { value() }
var timeIntervalSinceReferenceDate: TimeInterval { uint64.littleEndian.bitPattern }
var date: Date { .init(data: self) }
}
游乐场测试
let date = Date() // "Nov 15, 2019 at 12:13 PM"
let data = date.data // 8 bytes
print(Array(data)) // "[25, 232, 158, 22, 124, 191, 193, 65]\n"
let loadedDate = data.date // "Nov 15, 2019 at 12:13 PM"
print(date == loadedDate) // "true"
这是我如何使用 Leo Dabus 的答案。
public struct Timestamp: Equatable, Comparable {
public let date: Date
public init() {
self.date = Date()
}
public func toData() -> Data {
var date = self.date
return Data(bytes: &date, count: MemoryLayout<Date>.size)
}
public init(fromData data: Data) {
guard data.count == 8 else {
fatalError("Insufficient bytes. expected 8; got \(data.count). data: \(data)")
}
self.date = data.withUnsafeBytes { [=10=].pointee }
}
public static func ==(lhs: Timestamp, rhs: Timestamp) -> Bool {
return lhs.date == rhs.date
}
public static func <(lhs: Timestamp, rhs: Timestamp) -> Bool {
return lhs.date < rhs.date
}
}
我正在寻找一种 Swifty 方法来生成时间戳。
我的 macOS 应用程序记录了一些数据并在其上标记了创建数据的时间。然后数据将通过网络发送(如 Data
)以在 iPad.
是否有任何 Swift class 可以生成时间戳? NSDate? NSTimeIntervalSince1970? CFAbsoluteTimeGetCurrent()
要求是:
- 以尽可能少的字节存储时间戳(pref.
Int
) - 与真实地球时间有些相似(我宁愿不生成我的 自己的时间格式)
- 毫秒精度
- 构建速度快
- iOS 9+, macOS 10.10+
使用TimeIntervalSince1970
类型:
let exactTimeInMilliseconds = Date().timeIntervalSince1970
原来的回答效率很低。
您可以发送 Date
将其转换为 Data
(8 字节浮点数)并返回 Date
,如下所示:
extension Numeric {
var data: Data {
var source = self
return .init(bytes: &source, count: MemoryLayout<Self>.size)
}
init<D: DataProtocol>(_ data: D) {
var value: Self = .zero
let size = withUnsafeMutableBytes(of: &value, { data.copyBytes(to: [=10=])} )
assert(size == MemoryLayout.size(ofValue: value))
self = value
}
}
extension UInt64 {
var bitPattern: Double { .init(bitPattern: self) }
}
extension Date {
var data: Data { timeIntervalSinceReferenceDate.bitPattern.littleEndian.data }
init<D: DataProtocol>(data: D) {
self.init(timeIntervalSinceReferenceDate: data.timeIntervalSinceReferenceDate)
}
}
extension DataProtocol {
func value<N: Numeric>() -> N { .init(self) }
var uint64: UInt64 { value() }
var timeIntervalSinceReferenceDate: TimeInterval { uint64.littleEndian.bitPattern }
var date: Date { .init(data: self) }
}
游乐场测试
let date = Date() // "Nov 15, 2019 at 12:13 PM"
let data = date.data // 8 bytes
print(Array(data)) // "[25, 232, 158, 22, 124, 191, 193, 65]\n"
let loadedDate = data.date // "Nov 15, 2019 at 12:13 PM"
print(date == loadedDate) // "true"
这是我如何使用 Leo Dabus 的答案。
public struct Timestamp: Equatable, Comparable {
public let date: Date
public init() {
self.date = Date()
}
public func toData() -> Data {
var date = self.date
return Data(bytes: &date, count: MemoryLayout<Date>.size)
}
public init(fromData data: Data) {
guard data.count == 8 else {
fatalError("Insufficient bytes. expected 8; got \(data.count). data: \(data)")
}
self.date = data.withUnsafeBytes { [=10=].pointee }
}
public static func ==(lhs: Timestamp, rhs: Timestamp) -> Bool {
return lhs.date == rhs.date
}
public static func <(lhs: Timestamp, rhs: Timestamp) -> Bool {
return lhs.date < rhs.date
}
}