Is it possible to get the actual time in Swift? (not phone time)

I'm working on an application with a timer counting down from 1 hour where i need to show the seconds left on the screen. I need to do a calculation for defining the amount of seconds left. I do this calculation by comparing the current time Date() with tokenValidUntil date object and calculating the difference in seconds between the two objects.

The following code works as it should and returns the difference between the two date objects in seconds. However i have experienced a bug IF the user changes current time in settings, it affects the Date() object... I would like to be able to get the actual time in CET instead of getting the time of the phone, since the app should only be used in Denmark. I would love to get the actual time here no matter how the time is configured in settings.... Is this possible in any way? Of course i could find an API for getting the time but I would like to do it in swift if possible.. :thinking:

1 Like

Type Date represents moment in time, regardless of time zone. So you don't need Calendar to get number of seconds between two dates - timeIntervalSince(_:) will do the job. When printed in the debug console it may be formatted in the current time zone, but that is not what is stored inside.

If user changes time zone in the settings, it does not affect result of Date(). So you should not care if you are in CET or any other time zone. But if user manually changes the time - that effectively means your device travels in time, and results of Date() will change accordingly. Time that Date() returns is "now" for device's best knowledge.

If that's not what you are looking for, then maybe you are looking for monotonic clock. Monotonic clock always ticks forward and is not affected by changes in system time, but has undefined reference point. It allows you to accurately measure time elapsed between two events in the program. You can use monotonic clock to wait for 1h since button click, but you cannot use it to get number of seconds till timestamp returned by the server or entered by the user.

For monotonic clock you can use mach_continuous_time() + mach_timebase_info() to convert from ticks to seconds. Or you can use clock_gettime_nsec_np() as a convenience wrapper.

4 Likes

Thanks for your reply :raised_hands:

So, as you point out Date() is affected when you change the time manually in settings, and that is exactly my problem. What I really need is the correct time for "now" independent of phone settings.
I think you're right that what I might be looking for could be a monotonic clock, however I don't want to write in objective c in my codebase, so mach_continuous_time() is probably not the right choice for me..

Maybe the best Swift only solution could be to use an API for fetching "now" like http://worldtimeapi.org/ :thinking: .. or just ignoring the bug since it is a wierd edge case that only can happen if the user changes the time manually in settings

Date() gives you correct “now” to the best of system knowledge. If device is configured to have a particular current time, system has no reasons to assume that somewhere there is a different, more correct time. You app should trust that Date() is the correct time. Users normally don’t disable automatic time synchronization, but if they do - you should trust that they have reasons for that.

You should be able to use mach_continuous_time() and friends in Swift, you don’t need ObjC for that.

To help you decide if you should use Date() or monotonic clock, it would help if you explain how do you get tokenValidUntil.

I don’t think that http://worldtimeapi.org/ would help you much - this sounds like a poor man’s NTP.

2 Likes

The time could have been "wrong" initially and user now "corrected" it via settings... Are you talking about exam time deadline scenario and want to prohibit users cheating?