Ja, in C-Sprache. Der Funktionsname unterscheidet sich jedoch von "clock_gettime ()" unter Linux und "clock_get_time ()" unter OS X. Der Name der Struktur, die die Zeit in Nanosekunden darstellt, ist ebenfalls unterschiedlich. Das Verfahren zum Abrufen eines Zeitstempels unter Verwendung dieser Struktur ist ebenfalls unterschiedlich. Swift kann C-Sprachfunktionen verwenden, und Swift ist jetzt sowohl unter Linux als auch unter OS X verfügbar. Lassen Sie uns diesen Unterschied also mit Swift aufgreifen.
Versuchte es zu schaffen. Und auf GitHub veröffentlicht. Es ist eine MIT-Lizenz.
Es gibt nur eine Datei. Ich habe versucht, die Datei [TimeSpecification.swift] zu benennen (https://github.com/YOCKOW/SwiftTimeSpecification/blob/master/Sources/Library/TimeSpecification.swift). Und ich habe versucht, die Struktur in Swift "Time Specification" zu benennen. Die einzigen Eigenschaften (gespeicherte Eigenschaft) sind "Sekunden" und "Nanosekunden". Das Folgende ist ein Auszug und eine Erklärung. Die Reihenfolge der Erklärungen und die Reihenfolge des Codes in der Quelle stimmen nicht immer überein, also keine Angst ... Ich habe nichts Schwieriges getan. Das kann ich nicht sagen.
Importieren
, damit Sie die standardmäßige betriebssystemspezifische Bibliothek verwenden können. Glibc
für Linux, Darwin
für OS X.
Die Nanosekundenzeit wird unter Linux durch "struct timespec" und unter OS X durch "mach_timespec_t" ("typedef struct mach_timespec mach_timespec_t;") dargestellt. In beiden Fällen werden Sekunden durch das Element ".tv_sec" und Nanosekunden durch das Element ".tv_nsec" dargestellt. ".Tv_sec" ist jedoch "time_t" in "struct timespec", aber "unsigned int" [^ tv_sec_unsigned_int] in "mach_timespec_t" und ".tv_nsec" ist "long" und "clock_res_t" ("typedef int clock_res_t"). `) Aber der Inhalt ist völlig anders.
Nennen wir beide "CTimeSpec" einmal mit "typealias".
[^ tv_sec_unsigned_int]: 2106 issue tritt wahrscheinlich auf
#if os(Linux)
import Glibc
private typealias CTimeSpec = timespec
#elseif os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
private let mach_task_self:() -> mach_port_t = { return mach_task_self_ }
private typealias CTimeSpec = mach_timespec_t
#else
// UNKNOWN OS
#endif
Das Initialisieren der "Zeitspezifikation" mit der "C-Zeitspezifikation" ist einfach. Was Sie tun können, weil die Mitgliedsnamen für struct timespec
und mach_timespec_t
gleich sind:
extension TimeSpecification {
fileprivate init(_ cts:CTimeSpec) {
self.seconds = Int64(cts.tv_sec)
self.nanoseconds = Int32(cts.tv_nsec)
}
}
In Anbetracht der Verwendung wenden wir das Protokoll "Vergleichbar" an. Außerdem dachte ich, es wäre bequem, "ExpressibleByIntegerLiteral" und "ExpressibleByFloatLiteral" anzuwenden ... Wenn wir addieren oder subtrahieren, normalisieren wir auch "Nanosekunden", so dass es immer eine nicht negative ganze Zahl ist, so dass ein einmaliger Ausdruck eindeutig bestimmt wird.
public struct TimeSpecification: Comparable,
ExpressibleByIntegerLiteral,
ExpressibleByFloatLiteral {
public var seconds:Int64 = 0
public var nanoseconds:Int32 = 0 {
didSet { self.normalize() }
}
public init(seconds:Int64, nanoseconds:Int32) {
self.seconds = seconds
self.nanoseconds = nanoseconds
self.normalize()
}
public mutating func normalize() {
// `nanoseconds` must be always zero or positive value and less than 1_000_000_000
if self.nanoseconds >= 1_000_000_000 {
self.seconds += Int64(self.nanoseconds / 1_000_000_000)
self.nanoseconds = self.nanoseconds % 1_000_000_000
} else if self.nanoseconds < 0 {
// For example,
// (seconds:3, nanoseconds:-2_123_456_789)
// -> (seconds:0, nanoseconds:876_543_211)
self.seconds += Int64(self.nanoseconds / 1_000_000_000) - 1
self.nanoseconds = self.nanoseconds % 1_000_000_000 + 1_000_000_000
}
}
}
Ich habe mich gefragt, welche Art von Spezifikation ich verwenden soll, aber hier habe ich eine Aufzählung namens "Clock" definiert und versucht, sie mit dieser Methode zu erhalten. Holen Sie sich beispielsweise die Systemuhr mit let now = Clock.System.timeSpecification ()
.
Verwenden Sie in der Methode die C-Sprach-API unverändert. Anscheinend kann es fehlschlagen, also habe ich beschlossen, es als optional zurückzugeben.
Wenn Sie die Kalenderuhr in OS X angeben, können Sie die Zeit anscheinend nur in Mikrosekunden abrufen.
public enum Clock {
case Calendar
case System
public func timeSpecification() -> TimeSpecification? {
var c_timespec:CTimeSpec = CTimeSpec(tv_sec:0, tv_nsec:0)
let clock_id:CInt
var retval:CInt = -1
#if os(Linux)
clock_id = (self == .Calendar) ? CLOCK_REALTIME : CLOCK_MONOTONIC
retval = clock_gettime(clock_id, &c_timespec)
#elseif os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
var clock_name: clock_serv_t = 0
clock_id = (self == .Calendar) ? CALENDAR_CLOCK : SYSTEM_CLOCK
retval = host_get_clock_service(mach_host_self(), clock_id, &clock_name)
if retval != 0 { return nil }
retval = clock_get_time(clock_name, &c_timespec)
_ = mach_port_deallocate(mach_task_self(), clock_name)
#endif
return (retval == 0) ? TimeSpecification(c_timespec) : nil
}
}
Wenn überhaupt, das Ruby-Skript build-install.rb, mit dem die Bibliothek einfach erstellt werden kann Es dauerte eine lange Zeit. Obwohl es sich um ein Swift-Projekt handelt, macht Ruby-Code 40% aus. Tehe.