[Python-ideas] use gmtime(0) epoch in functions that use mktime()
Akira Li
4kir4.1i at gmail.com
Sat Sep 6 15:53:55 CEST 2014
Python uses "seconds since the epoch" term to describe time.time()
return value. POSIX term is "seconds since the Epoch" (notice the
capitalization) where Epoch is 1970-01-01 00:00:00+00:00. C99 term is
"calendar time" -- the encoding of the calendar time returned by the
time() function is unspecified.
Python documentation defines `epoch` as:
The :dfn:`epoch` is the point where the time starts. On January 1st
of that year, at 0 hours, the "time since the epoch" is zero. For
Unix, the epoch is 1970. To find out what the epoch is, look at
``gmtime(0)``.
time module documentation specifies calendar.timegm() as the inverse of
time.gmtime() while timegm() uses the fixed 1970 Epoch instead of
gmtime(0) epoch.
datetime.astimezone() (local_timezone()) passes Unix timestamp [1970] to
time.localtime() that may expect timestamp with different epoch
[gmtime(0)].
email.util.mktime_tz() uses both mktime() [gmtime(0)] and timegm() [1970].
mailbox.py uses both time.time() [gmtime(0)] and timegm() [1970].
http.cookiejar uses both EPOCH_YEAR=1970 and datetime.utcfromtimestamp()
[gmtime(0) epoch] for "seconds since epoch".
It seems 1970 Epoch is used for file times on Windows (os.stat()) but
os.path.getatime() refers to "seconds since epoch" [gmtime(0) epoch].
date{,time}.{,utc}fromtimestamp(), datetime.timestamp() docs equates
"POSIX timestamp" [1970 Epoch] and time.time()'s returned value
[gmtime(0) epoch].
datetime.timestamp() is inconsistent if gmtime(0) is not 1970. It uses
mktime() for naive datetime objects [gmtime(0) epoch]. But it
uses POSIX Epoch for aware datetime objects.
Correct me if I'm wrong here.
---
Possible fixes:
Say in the `epoch` definition that stdlib doesn't support
gmtime(0).tm_year != 1970.
OR don't use mktime() if 1970 Epoch is used e.g., create an aware
datetime object in the local timezone instead and use it to compute the
result with 1970 Epoch.
OR add *analog* of TZ=UTC time.mktime() and use it in stdlib where
necessary. Looking at previous attempts (e.g., [1], [2]) to implement
timegm(), the problem seems over-constrained. A different name could be
used, to avoid wrong expectations e.g., datetime could use
`(aware_datetime_object - gmtime0_epoch) // sec`
[1] http://bugs.python.org/issue6280,
[2] http://bugs.python.org/issue1667546
OR set EPOCH_YEAR=gmtime(0).tm_year instead of 1970 in
calendar.timegm(). It may break backward compatibility if there is a
system with non-1970 epoch. Deal on a case-by-case basis with other
places where 1970 Epoch is used. And drop "POSIX timestamp" [1970
Epoch] and use "seconds since the epoch" [gmtime(0) epoch] in the
datetime documentation. Change internal EPOCH year accordingly.
What is Python-ideas opinion about it?
--
Akira
More information about the Python-ideas
mailing list