Skip to content

Instantly share code, notes, and snippets.

@YOCKOW
Last active March 25, 2024 17:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save YOCKOW/12d9607cb30f40b79fb2 to your computer and use it in GitHub Desktop.
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.
/* *** *** *** *** *** *** *** *** *** *** *** *** ***
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
}
}
@maximveksler
Copy link

very well said!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment