Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is timeIntervalSince off by 1 consistently?

I’ve got a little timer functionality in my app. When the timer starts I create a date object and keep it as a property.

I then have a timer set in the code that repeatedly ticks every second and compares the stored property against Date() using timeIntervalSince. However, it looks like all positive values are off by 1 until they reach zero. The code remains on zero for two ticks and then starts calculating the results correctly from there on.

Is there any explanation for this discrepancy? More importantly, is there a guarantee that this behaviour will remain consistent so that I can adjust my own logic to handle it correctly? Unfortunately, I couldn’t find anything that could explain the behaviour in documentation.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Here is a minimum reproducible example of what I’m trying to achieve

import Combine
import Foundation

var cancellables = Set<AnyCancellable>()

let endDate = Date().addingTimeInterval(5)

Timer.publish(every: 1, on: .main, in: .common)
      .autoconnect()
      .sink { _ in
        let now = Date()
        print("End date: \(endDate)")
        print("Now: \(now)")
        print("Distance: \(Int(endDate.timeIntervalSince(now)))")
      }
      .store(in: &cancellables)

And the example output:

End date: 2023-03-14 07:11:28 +0000
Now: 2023-03-14 07:11:23 +0000
Distance: 4

End date: 2023-03-14 07:11:28 +0000
Now: 2023-03-14 07:11:24 +0000
Distance: 3

End date: 2023-03-14 07:11:28 +0000
Now: 2023-03-14 07:11:25 +0000
Distance: 2

End date: 2023-03-14 07:11:28 +0000
Now: 2023-03-14 07:11:26 +0000
Distance: 1

End date: 2023-03-14 07:11:28 +0000
Now: 2023-03-14 07:11:27 +0000
Distance: 0

End date: 2023-03-14 07:11:28 +0000
Now: 2023-03-14 07:11:28 +0000
Distance: 0

End date: 2023-03-14 07:11:28 +0000
Now: 2023-03-14 07:11:29 +0000
Distance: -1

End date: 2023-03-14 07:11:28 +0000
Now: 2023-03-14 07:11:30 +0000
Distance: -2

End date: 2023-03-14 07:11:28 +0000
Now: 2023-03-14 07:11:31 +0000
Distance: -3

>Solution :

TimeInterval is a floating point type with all its inadequacies. And the conversion to Int rounds always down by stripping off the fractional part.

A more reliable way is to let Calendar do the date math

print("Distance: \(Calendar.current.dateComponents([.second], from: now, to: endDate))")
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading