Je recherche un moyen Swifty de générer un horodatage.

Mon application macOS enregistre certaines données et les tamponne avec l'heure à laquelle les données ont été créées. Les données seront ensuite envoyées sur le réseau (sous la forme Data) pour être reconstruites sur un iPad.

Existe-t-il une classe Swift qui fonctionnera pour générer l'horodatage? NSDate? NSTimeIntervalSince1970? CFAbsoluteTimeGetCurrent ()

Les exigences sont les suivantes:

  1. Stockez l'horodatage en aussi peu d'octets que possible (préf. Int)
  2. Avoir un semblant de temps réel sur Terre (je préfère ne pas générer mon propre format d'heure)
  3. Précision à la milliseconde
  4. Rapide à construire
  5. iOS 9+, macOS 10.10+
1
MH175 27 nov. 2017 à 03:48

3 réponses

Meilleure réponse

Vous pouvez envoyer votre Date en le convertissant en Data (virgule flottante 8 octets) et le renvoyer vers Date comme suit:

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

Test de terrain de jeu

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"
3
Leo Dabus 9 févr. 2020 à 14:13

Utilisez le type TimeIntervalSince1970:

let exactTimeInMilliseconds = Date().timeIntervalSince1970

La réponse originale était très inefficace.

0
Xcoder 27 nov. 2017 à 15:56

Voici comment j'ai utilisé la réponse de 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 { $0.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
    }
}
0
MH175 27 nov. 2017 à 02:51
47502591