swifttimestampnsdatenstimeinterval

Convert a Date (absolute time) to be sent/received across the network as Data in Swift?


I am looking for a Swifty way to generate a timestamp.

My macOS app logs some data and stamps it with the time the data was created. The data will then be sent across the network (as Data) to be reconstructed on an iPad.

Is there any Swift class that will work to generate the timestamp? NSDate? NSTimeIntervalSince1970? CFAbsoluteTimeGetCurrent()

The requirements are:

  1. Store the timestamp in as few bytes as possible (pref. Int)
  2. Have some semblance to real Earth time (I'd rather not generate my own time format)
  3. Millisecond accuracy
  4. Fast to construct
  5. iOS 9+, macOS 10.10+

Solution

  • You can send your Date converting it to Data (8-bytes floating point) and back to Date as follow:

    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: $0)} )
            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) }
    }
    

    Playground Testing

    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"