5

What happens when the clock of the computer running python (Windows or Linux) gets automatically changed and a call time.time()?

I've read that the value of time.time() will be smaller when the clock is changed manually to some value in the past.

MattDMo
  • 100,794
  • 21
  • 241
  • 231
David Stark
  • 61
  • 1
  • 4
  • Just try it and see what happens. – President James K. Polk Sep 09 '15 at 00:53
  • Does changing the clock under Windows change the UTC value or my locale time value? Edit: Mhh guess changing the Timezone will do it? – David Stark Sep 09 '15 at 00:57
  • related: [How does python's time.time() method work?](http://stackoverflow.com/q/27830403/4279) – jfs Sep 09 '15 at 13:41
  • Changing the clock (via control panel, command line, or OS function) usually takes local time as *input*, but ultimately has to translate that to UTC before setting it via Windows's `SetSystemTime` call. The OS tracks only UTC internally. Local time conversions are done for input, display, and when writing to the BIOS, etc. Note that changing the time zone does NOT change the UTC value being tracked. It only changes the zone used during the conversions. – Matt Johnson-Pint Sep 10 '15 at 21:55

3 Answers3

4

time.time() docs state:

Return the time in seconds since the epoch as a floating point number.

The particular epoch referred to here is the Unix epoch, which is Midnight, Jan 1st 1970 UTC.

Since it is always based on UTC, it will not be affected by changing the computer's time zone, nor when the computer's time zone enters or exits daylight saving time.

Though the function does rely on the underlying implementation to provide the value, those implementations always return values in terms of UTC - regardless of operating system.

On Windows in particular, it ultimately calls the GetSystemTimeAsFileTime OS function, which returns its value in terms of UTC. It is not affected by time zone selection or by DST changes within the time zone.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • it is not so simple. UTC time and what OS thinks is UTC time may differ. – jfs Sep 11 '15 at 03:59
  • Well sure, if you're talking about the clock being in sync, and how *well* synchronized it is. But that's not what we're talking about here... – Matt Johnson-Pint Sep 11 '15 at 14:02
  • I'm talking about the possible difference for *any* reason. Let's assume that before the local timezone has been changed, the clock was precise: are you claiming that you can keep previous values for both UTC and local time regardless how you change local timezone settings? For example, imagine you've change the UTC offset while keeping local time the same: your claim is that UTC time also stays the same that makes the system inconsistent because it can't be if old and new UTC offsets are different (local = utc + offset: you can't preserve both *local* and *utc* if *offset* has changed). – jfs Sep 11 '15 at 14:13
  • No, I'm not claiming what you described. I'm simply stating that if the clock is precise with respect to UTC, then after changing the time zone the clock is *still* precise with respect to UTC. The local time may now show differently on the Windows taskbar then it did previously, but the underlying UTC values are not modified. – Matt Johnson-Pint Sep 11 '15 at 15:24
  • Unless you are claiming that it is impossible to preserve local time while changing local timezone (I don't care how as long as it is possible); my point stands -- `time.time()` value may change even if *all* you need is to change local timezone while preserving local time. – jfs Sep 11 '15 at 15:36
  • @J.F.Sebastian - Yes, that's exactly correct. It is impossible to preserve local time while changing local time zone. You can change the time zone, or you can change the time, but you can't do both simultaneously. I am only claiming that time zone changes will not affect `time.time()`. I'm not claiming that changing the *time* will not affect things. – Matt Johnson-Pint Sep 11 '15 at 15:43
  • At the very lowest public API level, the Windows calls are [`SetSystemTime`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724942.aspx) and [`SetDynamicTimeZoneInformation`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724932.aspx). The former only takes time in terms of UTC, and the latter does not take in time at all. (It's no different internally either.) – Matt Johnson-Pint Sep 11 '15 at 15:53
  • I don't dispute that it may take multiple steps. Imagine your hardware clock is interpreted as local time (Windows often does it), the local time itself is correct but you've noticed that UTC time is wrong because the local timezone is set incorrectly: you fix the timezone, the local time stays the same (correct) value, utc time changes. – jfs Sep 12 '15 at 11:03
2

Quoting the docs for time.time,

While this function normally returns non-decreasing values, it can return a lower value than a previous call if the system clock has been set back between the two calls.

What adjusts the value of the system clock is platform dependent. But, per the comments, that shouldn't include changes based on DST, since all OSs that Python supports provide system calls for retrieving the current time in UTC (and DST only affects how local time relates to UTC).

If that isn't a good enough guarantee, you might prefer time.montonic, which is guaranteed to never go backward - however, note that it comes with this caveat (and decide whether this matters for your use case):

The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid.

lvc
  • 34,233
  • 10
  • 73
  • 98
  • [Clock time is off on dual boot](http://askubuntu.com/q/169376/3712) says that both utc and local time options could be used by Linux and Windows. It is more likely that Windows sets hardware clock to the local time. It is not clear what `GetSystemTimeAsFileTime()` (used by `time.time()`) returns if only DST settings are changed (if it is possible: same local time, different DST setting implies different utc offset and therefore a possible different utc time -- otherwise the system will be inconsistent). – jfs Sep 09 '15 at 13:47
  • Windows system time is also in terms of UTC. Only the BIOS is written as local time. Translation occurs automatically on startup, and whenever the local time changes (for DST, NTP, or user modification) but UTC is what is tracked by the OS, and it doesn't change for DST or other timezone changes. Note that the docs for [GetSystemTimeAsFileTime](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724397.aspx) clearly state the return value is in UTC. – Matt Johnson-Pint Sep 10 '15 at 21:43
  • @MattJohnson: (1) I've been bitten so many times by the lies in msdn that I don't trust it until the corresponding claims are tested on relevant systems (2) the value (similar to POSIX timestamp) is not in any timezone though [`GetSystemTimeAsFileTime()` (100s of nanoseconds since 1600) can be converted to UTC easily](http://stackoverflow.com/a/28574340/4279). I won't guess what happens if DST setting is changed (not *transition* but *setting* e.g., different local timezone is set while keeping the same local time) – jfs Sep 11 '15 at 03:54
  • Changing the time zone is independent from changing the time. When you change the time zone, the local time is updated automatically by converting the system time to the new time zone. So one cannot keep the same local time while changing only the time zone (unless those two time zones just happen to be aligned for the current time). In other words, if it's 7:00 local time on my clock, and I change my time zone from Pacific to Eastern (with DST in effect), my local clock will now read 10:00, because the underlying UTC time of 14:00 did not change (other than the normal ticking forward). – Matt Johnson-Pint Sep 11 '15 at 14:09
  • @MattJohnson: I've explicitly said that the local time is preserved. – jfs Sep 11 '15 at 14:24
  • @J.F.Sebastian - I know. That's why I'm trying to tell you that that's not how it works on Windows. The local time is not what is preserved. One sets the time and the time zone independently. To preserve the local time, you would have to both change the time zone and then separately go and adjust the clock. – Matt Johnson-Pint Sep 11 '15 at 15:16
  • @MattJohnson: that is my point: even if you need to change *only* local timezone settings; you might end up changing `time.time()` result. – jfs Sep 11 '15 at 15:24
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/89402/discussion-between-matt-johnson-and-j-f-sebastian). – Matt Johnson-Pint Sep 11 '15 at 15:24
1

time.time() returns the value what the underlying library returns. Python uses time(..) or gettimeofday(.., nullptr) (depending whats available on the system).

https://github.com/python-git/python/blob/master/Modules/timemodule.c#L874

In both cases UTC is returned. E.g:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/time.html

The time() function shall return the value of time in seconds since the Epoch

After a valid comment of Matt I have to add the definition of epoch which clearly states that time returns the UTC time.

Epoch: Historically, the origin of UNIX system time was referred to as "00:00:00 GMT, January 1, 1970". Greenwich Mean Time is actually not a term acknowledged by the international standards community; therefore, this term, "Epoch", is used to abbreviate the reference to the actual standard, Coordinated Universal Time.

To proove the epoch is the same check this:

import time
a = time.gmtime(secs=0)
# time.struct_time(tm_year=2015, tm_mon=9, tm_mday=9, tm_hour=1, tm_min=3, tm_sec=28, tm_wday=2, tm_yday=252, tm_isdst=0)
b = time.localtime(secs=0)
# time.struct_time(tm_year=2015, tm_mon=9, tm_mday=9, tm_hour=3, tm_min=1, tm_sec=28, tm_wday=2, tm_yday=252, tm_isdst=1)

Both functions use the value returned from time.time() if the parameter secs is 0. In my case tm_isdst was set to true for the localtime, and false for the gmtime (which represents the time since the epoch).

Edit: Where have you read that the value will be smaller?

HelloWorld
  • 2,392
  • 3
  • 31
  • 68