Last active
March 25, 2024 17:41
-
-
Save YOCKOW/12d9607cb30f40b79fb2 to your computer and use it in GitHub Desktop.
Get `timespec` in Swift. It is no longer necessary to implement clock_gettime() even on OS X.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* *** *** *** *** *** *** *** *** *** *** *** *** *** | |
Now, migrated to GitHub: | |
https://github.com/YOCKOW/SwiftTimeSpecification | |
This gist will not be updated. | |
*** *** *** *** *** *** *** *** *** *** *** *** *** */ | |
/* TimeSpecification.swift | |
* © 2016 YOCKOW. | |
* You can do whatever you want with this code AT YOUR OWN RISK. | |
*/ | |
// <Usage> | |
// let now:TimeSpecification? = Clock.Calendar.timeSpecification() | |
// if now != nil { | |
// let (sec, nsec) = (now!.seconds, now!.nanoseconds) | |
// /* ... */ | |
// } | |
// You can play at http://swiftlang.ng.bluemix.net/#/repl/6232922e1f9833c8800ffdbe1e9f6b65f5deb8f78a6ceb8c47caae3444ac3f3f | |
#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 | |
public struct TimeSpecification { | |
var seconds:Int64 | |
var nanoseconds:Int32 | |
private init(_ cts:CTimeSpec) { | |
seconds = Int64(cts.tv_sec) | |
nanoseconds = Int32(cts.tv_nsec) | |
} | |
} | |
extension Double { | |
public init(_ ts: TimeSpecification) { | |
self = Double(ts.nanoseconds) * 1.0E-9 + Double(ts.seconds) | |
} | |
} | |
extension TimeSpecification { | |
public func toDouble() -> Double { | |
return Double(self) | |
} | |
} | |
public func + (lhs:TimeSpecification, rhs:TimeSpecification) -> TimeSpecification { | |
var result = lhs | |
result.seconds += rhs.seconds | |
result.nanoseconds += rhs.nanoseconds | |
if (result.nanoseconds >= 1_000_000_000) { | |
result.seconds += 1 | |
result.nanoseconds -= 1_000_000_000 | |
} | |
return result | |
} | |
public func - (lhs:TimeSpecification, rhs:TimeSpecification) -> TimeSpecification { | |
var result = lhs | |
result.seconds -= rhs.seconds | |
result.nanoseconds -= rhs.nanoseconds | |
if (result.nanoseconds < 0) { | |
result.seconds -= 1 | |
result.nanoseconds += 1_000_000_000 | |
} | |
return result | |
} | |
public func == (lhs:TimeSpecification, rhs:TimeSpecification) -> Bool { | |
if lhs.seconds != rhs.seconds { return false } | |
if lhs.nanoseconds != rhs.nanoseconds { return false } | |
return true | |
} | |
public func != (lhs:TimeSpecification, rhs:TimeSpecification) -> Bool { | |
return (lhs == rhs) ? false : true | |
} | |
public func < (lhs:TimeSpecification, rhs:TimeSpecification) -> Bool { | |
if lhs.seconds < rhs.seconds { return true } | |
if lhs.seconds > rhs.seconds { return false } | |
// then, lhs.seconds == rhs.seconds | |
if (lhs.nanoseconds < rhs.nanoseconds) { return true } | |
return false | |
} | |
public func > (lhs:TimeSpecification, rhs:TimeSpecification) -> Bool { | |
if lhs.seconds > rhs.seconds { return true } | |
if lhs.seconds < rhs.seconds { return false } | |
// then, lhs.seconds == rhs.seconds | |
if (lhs.nanoseconds > rhs.nanoseconds) { return true } | |
return false | |
} | |
public func <= (lhs:TimeSpecification, rhs:TimeSpecification) -> Bool { | |
return !(lhs > rhs) | |
} | |
public func >= (lhs:TimeSpecification, rhs:TimeSpecification) -> Bool { | |
return !(lhs < rhs) | |
} | |
public enum Clock { | |
case Calendar | |
case System | |
public func timeSpecification() -> TimeSpecification? { | |
var result:CTimeSpec = CTimeSpec(tv_sec:0, tv_nsec:0) | |
let clock_id:CInt | |
var successful:CInt = -1 | |
#if os(Linux) | |
clock_id = (self == .Calendar) ? CLOCK_REALTIME : CLOCK_MONOTONIC | |
successful = clock_gettime(clock_id, &result) | |
#elseif os(OSX) || os(iOS) || os(watchOS) || os(tvOS) | |
clock_id = (self == .Calendar) ? CALENDAR_CLOCK : SYSTEM_CLOCK | |
var clock_name: clock_serv_t = 0 | |
successful = host_get_clock_service(mach_host_self(), clock_id, &clock_name) | |
if successful != 0 { return nil } | |
successful = clock_get_time(clock_name, &result) | |
_ = mach_port_deallocate(mach_task_self(), clock_name) | |
#endif | |
return (successful == 0) ? TimeSpecification(result) : nil | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
very well said!