This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Incorrect documentation - UTC time
Type: Stage:
Components: Documentation Versions: Python 3.1, Python 3.2, Python 2.7, Python 2.6
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: belopolsky Nosy List: belopolsky, georg.brandl, lemburg, loewis, luckmor
Priority: normal Keywords:

Created on 2008-12-30 02:17 by luckmor, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (9)
msg78497 - (view) Author: David Morley (luckmor) Date: 2008-12-30 02:17
There is a systemic error in the Python documentation on time (such as 
<http://docs.python.org/library/time.html>). The term UTC is used 
incorrectly in the documentation where the term UT1 should be used.

The difference is that UTC includes leap seconds, whereas UT1 does not (see <http://en.wikipedia.org/wiki/Coordinated_Universal_Time>). The 
conversion routines ignore leap seconds, e.g., (time.mktime((2000,1,1,12,0,0,0,0,0))-
time.mktime((1990,1,1,12,0,0,0,0,0))) returns an exact multiple of 
24*60*60 and does not include all the leap seconds added between those 
dates. Using UT1 is more sensible that using UTC, since with UTC it is 
impossible to know when future leap seconds will be added, and hence 
impossible to convert future times to a number of seconds past the 
epoch.
msg78512 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2008-12-30 08:46
> The difference is that UTC includes leap seconds, whereas UT1 does not (see <http://en.wikipedia.org/wiki/Coordinated_Universal_Time>). The 
> conversion routines ignore leap seconds, e.g., (time.mktime((2000,1,1,12,0,0,0,0,0))-
> time.mktime((1990,1,1,12,0,0,0,0,0))) returns an exact multiple of 
> 24*60*60 and does not include all the leap seconds added between those 
> dates. 

Read the documentation carefully. It doesn't claim that mktime uses UTC,
and claiming that it uses UT1 would be equally incorrect. Instead,
mktime uses local time (as documented). Whether that includes leap
seconds or not depends on the definition of your time zone in your
operating system.

Also notice that the Unix time (time_t) is discontinuous with respect
to leap seconds; each day time_t advances by 86400 seconds even if there
was a leap second on that day; see

http://en.wikipedia.org/wiki/Unix_time

So even if your time zone includes leap seconds, then mktime still
correctly computes the difference as multiple of 86400.

Which specific other usage of UTC do you also consider incorrect?
msg78523 - (view) Author: David Morley (luckmor) Date: 2008-12-30 12:21
- My use of mktime was a bad choice for an example, since "local time" 
is not defined and does not necessarily bear any relationship to UTC. 
However the documentation does claim that time.gmtime converts "a time 
expressed in seconds since the epoch" to "a struct_time in UTC".

- You are no doubt correct that under Unix, "Unix time" is actually 
used, however the phrase "a time expressed in seconds since the epoch" 
implies the number of *elapsed* seconds since the epoch, which is not 
the same thing as Unix time. It was the fact that (at least under Mac OS 
X) the numeric representation assumes a 86400 second day that led me to 
believe that non-SI seconds and hence a non-UTC version of Universal 
Time, such as UT1 was being used.

The documentation should make it clear either that 

(1) the numeric representation of times is based on Unix time and 
assumes a 86400 SI second day, and therefore (1a) the number of elapsed 
SI seconds between two numeric times is not necessarily equal to the 
difference of those two numbers and (1b) gmtime accurately converts a 
UTC time, or that

(2) the numeric representation of times is based on a 86400 non-SI 
second day, and therefore (2a) the number of elapsed (non-SI) seconds 
between two numeric times is equal to the difference of the two numbers 
and (2b) gmtime accurately converts a non-UTC Universal Time, or that

(3) the numeric representation of times is based on TAI and assumes a 
86400 SI second day, and therefore (1a) the number of elapsed SI seconds 
between two numeric times is equal to the difference of those two 
numbers and (1b) gmtime accurately converts a TAI time, or that

(4) the numeric representation of time is based on SI-seconds past the 
epoch and allows variable length days, and therefore (4a) the number of 
elapsed SI seconds between two numeric times is equal to the difference 
of the two numbers and (4b) gmtime only accurately converts a UTC time 
that is before the next future leap-second adjustment (whenever that may 
be), or that

(5) the numeric representation of time is platform-dependent and any one 
of the above may hold. 

Note that the only significant difference in implementation between (1), 
(2), and (3) is what time.time() actually returns: Unix time, a non-UTC 
Universal Time, or TAI.

Since the time.localtime is most-likely implemented as an integral-
minute offset from time.gmtime, the same issues arise for time.localtime 
and time.mktime.

The same documentation issue crops up in 
<http://docs.python.org/library/datetime.html> and indirectly 
(calendar.timegm) in <http://docs.python.org/library/calendar.html>
msg78527 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2008-12-30 13:13
> It was the fact that (at least under Mac OS X) the numeric
> representation assumes a 86400 second day that led me to
> believe that non-SI seconds and hence a non-UTC version of Universal
> Time, such as UT1 was being used.

AFAICT, Mac OSX also uses Unix time...

Why do you think UT1 plays any role here? Computers *have* to use
SI seconds, since they are not physically equipped to measure
anything else (unless you want to get even more nit-picking and point
out that the quartz in the computer is not capable of measuring
SI seconds exactly).

> (5) the numeric representation of time is platform-dependent 

This is the case.

> and any one of the above may hold. 

This is not consequential. As it is platform dependent, it might do
any of the above, plus an infinite number of additional alternatives
(including bugs and whatnot).

I propose to add this sentence to the explanation of the epoch:

"It is platform-dependent whether or not 'seconds since the epoch'
includes leap seconds. Most systems likely implement `Unix time`_"

_ http://en.wikipedia.org/wiki/Unix_time

> The same documentation issue crops up in 
> <http://docs.python.org/library/datetime.html> and indirectly 
> (calendar.timegm) in <http://docs.python.org/library/calendar.html>

Please, one issue at a time. I believe that this doesn't crop up,
or if it does, it's a different issue. If you want to pursue this,
please create a separate report, and preferably include a proposed
wording.
msg78591 - (view) Author: David Morley (luckmor) Date: 2008-12-31 06:48
> I propose to add this sentence to the explanation of the epoch:
>
> "It is platform-dependent whether or not 'seconds since the epoch'
> includes leap seconds. Most systems likely implement `Unix time`_"

That solution is fine.

Anyone sufficiently concerned about the implications can then work out 
the consequences for themselves once alerted.

> Please, one issue at a time. I believe that this doesn't crop up,
> or if it does, it's a different issue. If you want to pursue this,
> please create a separate report, and preferably include a proposed
> wording.

This was in response to your request for "specific other usage of UTC". 
The datetime module uses the term UTC very frequently but assumes a 
fixed 86400 second day (which is incompatible with UTC but compatible 
with the other Universal Times). I see this as the same issue, that is, when leap-seconds are not used it seems odd to use the more specific 
term "UTC" rather than the less specific "GMT" or "UT" - "UTC" is a more 
precise but in this case less accurate term.

...but I am happy to drop this if you don't consider it a problem.

> Why do you think UT1 plays any role here?

To me, but maybe not to anyone else :-), property (1a) eliminates the 
usefulness of the numerical representation of time for interpretation 
(1) of the time routines.

Of the non-UTC versions of Universal Time why did I assume UT1 
specifically? UT1 is the main Universal Time - the one that UTC attempts 
to approximate.

> Computers *have* to use
> SI seconds, since they are not physically equipped to measure
> anything else (unless you want to get even more nit-picking and point
> out that the quartz in the computer is not capable of measuring
> SI seconds exactly).

Well, the different Universal Times *are* nit-picking over defining 
seconds :-) Without the nit-picking, we would have GMT.
msg78729 - (view) Author: Marc-Andre Lemburg (lemburg) * (Python committer) Date: 2009-01-01 21:39
FWIW: POSIX defines Unix time_t *not* to include leap seconds.

You can easily check whether your platform or C lib behaves
POSIX-ly correct or not:

   POSIX: 1986-12-31 23:59:59 UTC == 536457599 ticks

   With leap seconds:		  == 536457612 ticks

   (since there were 13 leap seconds in the years 1972-1985)

For most practical purposes the difference doesn't really matter,
since date differences are usually counted in days, not seconds.

In cases where it does matter, you're better off with a custom
solution, since applications or other libraries tend not to handle
leap seconds well.
msg108673 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-26 01:25
Python implementation of time functions certainly has nothing to do with UT1, which is the time as measured by (modern) sun dials.  The correct name would be POSIX time.  As explained in POSIX rationale,

"""
Coordinated Universal Time (UTC) includes leap seconds. However, in POSIX time (seconds since the Epoch), leap seconds are ignored (not applied) to provide an easy and compatible method of computing time differences. Broken-down POSIX time is therefore not necessarily UTC, despite its appearance.
""" -- http://www.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html

Nevertheless, UTC time is used throughout the standard.  For example,

"""
The gmtime() function shall convert the time in seconds since the Epoch pointed to by timer into a broken-down time, expressed as Coordinated Universal Time (UTC).
""" -- http://www.opengroup.org/onlinepubs/9699919799/functions/gmtime.html


I don't think there is much that can be improved in the Python documentation other than to stop referring to UTC as if it was a geographical location.
msg108675 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-26 01:30
"""
The gmtime() function shall convert the time in seconds since the Epoch pointed to by timer into a broken-down time, expressed as Coordinated Universal Time (UTC).
"""

In a technical sense, this is correct.  The result of gmtime() is UTC time, but it fails to mention that gmtime() will never produce tm_sec=60.
msg117948 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-10-04 14:08
Based on the discussion so far, I am going to close this as "invalid".
History
Date User Action Args
2022-04-11 14:56:43adminsetgithub: 49025
2010-10-08 18:50:25belopolskysetstatus: pending -> closed
2010-10-04 14:08:11belopolskysetstatus: open -> pending
assignee: georg.brandl -> belopolsky
resolution: not a bug
messages: + msg117948
2010-06-26 01:30:36belopolskysetmessages: + msg108675
2010-06-26 01:25:44belopolskysetnosy: + belopolsky
messages: + msg108673
2010-06-25 22:09:46terry.reedysetversions: + Python 2.6, Python 3.1, Python 2.7, Python 3.2, - Python 2.5
2009-01-01 21:39:51lemburgsetnosy: + lemburg
messages: + msg78729
2008-12-31 06:48:20luckmorsetmessages: + msg78591
2008-12-30 13:13:31loewissetmessages: + msg78527
2008-12-30 12:21:59luckmorsetmessages: + msg78523
2008-12-30 08:47:02loewissetnosy: + loewis
messages: + msg78512
2008-12-30 02:17:21luckmorcreate