11

I need to subtract a DispatchTimeInterval from an NSTimeInterval (or Double).

Is there a standard way to convert a DispatchTimeInterval to an NSTimeInterval?

meaning-matters
  • 21,929
  • 10
  • 82
  • 142
  • DispatchTimeInterval is used with DispatchTime, not with (NS)Date or (NS)TimeInterval. Can you tell more about why you need this? – In any case, DispatchTimeInterval is an enum, and converting it to a Double would be a matter of a simple switch/case. – Martin R Dec 08 '17 at 12:58
  • @MartinR There's a timer which is set with a `DispatchTimeInterval` and I measure elapsed real time in `NSTimeInterval`. I need to subtract both to get a delay. – meaning-matters Dec 08 '17 at 13:50

3 Answers3

18

DispatchTimeInterval is a enum:

public enum DispatchTimeInterval : Equatable {
    case seconds(Int)
    case milliseconds(Int)
    case microseconds(Int)
    case nanoseconds(Int)
    case never
}

You can initialize DispatchTimeInterval using:

    let tenSeconds: DispatchTimeInterval = .seconds(10)
    let tenNanoseconds: DispatchTimeInterval = .nanoseconds(10)

To get values from enum you need to match value with a case values in enum

    if case .seconds(let value) = tenSeconds {
        print("DispatchTimeInterval is seconds \(value)")
    } else if case .nanoseconds(let value) = tenNanoseconds {
        print("DispatchTimeInterval is seconds \(value)")
    }

Converting function might be look following:

func toDouble(_ interval: DispatchTimeInterval) -> Double? {
        var result: Double? = 0

        switch interval {
        case .seconds(let value):
            result = Double(value)
        case .milliseconds(let value):
            result = Double(value)*0.001
        case .microseconds(let value):
            result = Double(value)*0.000001
        case .nanoseconds(let value):
            result = Double(value)*0.000000001

        case .never:
            result = nil
        }

        return result
    }

More about Enumeration see in Apple Documentation

UPDATE:

Create extension to DispatchTimeInterval

extension DispatchTimeInterval {
    func toDouble() -> Double? {
        var result: Double? = 0

        switch self {
        case .seconds(let value):
            result = Double(value)
        case .milliseconds(let value):
            result = Double(value)*0.001
        case .microseconds(let value):
            result = Double(value)*0.000001
        case .nanoseconds(let value):
            result = Double(value)*0.000000001

        case .never:
            result = nil
        }

        return result
    }
}
Ihar Katkavets
  • 1,510
  • 14
  • 25
11

A swifty solution would be to create a TimeInterval extension and add a failable initializer with a DispatchTimeInterval parameter in it. The following Swift 5 code shows how to implement it:

import Foundation

extension TimeInterval {

    init?(dispatchTimeInterval: DispatchTimeInterval) {
        switch dispatchTimeInterval {
        case .seconds(let value):
            self = Double(value)
        case .milliseconds(let value):
            self = Double(value) / 1_000
        case .microseconds(let value):
            self = Double(value) / 1_000_000
        case .nanoseconds(let value):
            self = Double(value) / 1_000_000_000
        case .never:
            return nil
        }
    }

}

Usage:

let dispatchTimeInterval = DispatchTimeInterval.seconds(5)
let timeInterval = TimeInterval(dispatchTimeInterval: dispatchTimeInterval)
print(String(describing: timeInterval)) // Optional(5.0)
let dispatchTimeInterval = DispatchTimeInterval.milliseconds(30)
let timeInterval = TimeInterval(dispatchTimeInterval: dispatchTimeInterval)
print(String(describing: timeInterval)) // Optional(0.03)
Imanou Petit
  • 89,880
  • 29
  • 256
  • 218
2

A very neat and simple solution is this one (no need for switch statements):

extension DispatchTimeInterval {
  var nanoseconds: UInt64 {
    let now = DispatchTime.now()
    let later = now.advanced(by: self)
    return later.uptimeNanoseconds - now.uptimeNanoseconds
  }

  var timeInterval: TimeInterval {
    return Double(nanoseconds) / Double(NSEC_PER_SEC)
  }
}
Fab1n
  • 2,103
  • 18
  • 32