mirror of https://github.com/python/cpython
datetime_from_timet_and_us(): ignore leap seconds if the platform
localtime()/gmtime() insists on delivering them, + associated doc changes. Redid the docs for datetimtez.astimezone().
This commit is contained in:
parent
85e4c6757f
commit
75a6e3bd1a
|
@ -314,8 +314,9 @@ Other constructors, all class methods:
|
|||
\exception{ValueError}, if the timestamp is out of the range of
|
||||
values supported by the platform C \cfunction{localtime()}
|
||||
function. It's common for this to be restricted to years from 1970
|
||||
through 2038.
|
||||
\end{methoddesc}
|
||||
through 2038. Note that on non-POSIX systems that include leap
|
||||
seconds in their notion of a timestamp, leap seconds are ignored by
|
||||
\method{fromtimestamp()}.
|
||||
|
||||
\begin{methoddesc}{fromordinal}{ordinal}
|
||||
Return the date corresponding to the proleptic Gregorian ordinal,
|
||||
|
@ -546,6 +547,11 @@ Other constructors, all class methods:
|
|||
range of values supported by the platform C
|
||||
\cfunction{localtime()} function. It's common for this to be
|
||||
restricted to years in 1970 through 2038.
|
||||
Note that on non-POSIX systems that include leap seconds in their
|
||||
notion of a timestamp, leap seconds are ignored by
|
||||
\method{fromtimestamp()}, and then it's possible to have two timestamps
|
||||
differing by a second that yield identical \class{datetime} objects.
|
||||
\end{methoddesc}
|
||||
See also \method{utcfromtimestamp()}.
|
||||
\end{methoddesc}
|
||||
|
||||
|
@ -988,16 +994,18 @@ April, and ends the minute after 1:59 (EDT) on the last Sunday in October:
|
|||
|
||||
When DST starts (the "start" line), the local wall clock leaps from 1:59
|
||||
to 3:00. A wall time of the form 2:MM doesn't really make sense on that
|
||||
day, so astimezone(Eastern) won't deliver a result with hour=2 on the
|
||||
day DST begins. How an Eastern class chooses to interpret 2:MM on
|
||||
that day is its business. The example Eastern class above chose to
|
||||
day, so \code{astimezone(Eastern)} won't deliver a result with
|
||||
\code{hour==2} on the
|
||||
day DST begins. How an Eastern instance chooses to interpret 2:MM on
|
||||
that day is its business. The example Eastern implementation above
|
||||
chose to
|
||||
consider it as a time in EDT, simply because it "looks like it's
|
||||
after 2:00", and so synonymous with the EST 1:MM times on that day.
|
||||
Your Eastern class may wish, for example, to raise an exception instead
|
||||
when it sees a 2:MM time on the day Eastern begins.
|
||||
when it sees a 2:MM time on the day EDT begins.
|
||||
|
||||
When DST ends (the "end" line), there's a potentially worse problem:
|
||||
there's an hour that can't be spelled at all in local wall time, the
|
||||
there's an hour that can't be spelled unambiguously in local wall time, the
|
||||
hour beginning at the moment DST ends. In this example, that's times of
|
||||
the form 6:MM UTC on the day daylight time ends. The local wall clock
|
||||
leaps from 1:59 (daylight time) back to 1:00 (standard time) again.
|
||||
|
@ -1005,11 +1013,12 @@ leaps from 1:59 (daylight time) back to 1:00 (standard time) again.
|
|||
2:MM is taken as standard time (it's "after 2:00"), so maps to 7:MM UTC.
|
||||
There is no local time that maps to 6:MM UTC on this day.
|
||||
|
||||
Just as the wall clock does, astimezone(Eastern) maps both UTC hours 5:MM
|
||||
Just as the wall clock does, \code{astimezone(Eastern)} maps both UTC
|
||||
hours 5:MM
|
||||
and 6:MM to Eastern hour 1:MM on this day. However, this result is
|
||||
ambiguous (there's no way for Eastern to know which repetition of 1:MM
|
||||
is intended). Applications that can't bear such ambiguity even one hour
|
||||
per year should avoid using hybrid tzinfo classes; there are no
|
||||
is intended). Applications that can't bear such ambiguity
|
||||
should avoid using hybrid tzinfo classes; there are no
|
||||
ambiguities when using UTC, or any other fixed-offset tzinfo subclass
|
||||
(such as a class representing only EST (fixed offset -5 hours), or only
|
||||
EDT (fixed offset -4 hours)).
|
||||
|
@ -1354,19 +1363,24 @@ Instance methods:
|
|||
\end{methoddesc}
|
||||
|
||||
\begin{methoddesc}{astimezone}{tz}
|
||||
Return a \class{datetimetz} with new tzinfo member \var{tz}. \var{tz}
|
||||
must be \code{None}, or an instance of a \class{tzinfo} subclass. If
|
||||
\var{tz} is \code{None}, self is naive, or
|
||||
Return a \class{datetimetz} object with new \membar{tzinfo} member
|
||||
\var{tz}.
|
||||
\var{tz} must be \code{None}, or an instance of a \class{tzinfo} subclass.
|
||||
If \var{tz} is \code{None}, \var{self} is naive,
|
||||
\code{tz.utcoffset(self)} returns \code{None},
|
||||
or \code{self.tzinfo}\ is \var{tz},
|
||||
\code{self.astimezone(tz)} is equivalent to
|
||||
\code{self.replace(tzinfo=tz)}: a new timezone object is attached
|
||||
without any conversion of date or time fields. If self is aware and
|
||||
\code{tz.utcoffset(self)} does not return \code{None}, the date and
|
||||
time fields are adjusted so that the result is local time in timezone
|
||||
tz, representing the same UTC time as self.
|
||||
XXX [The treatment of endcases remains unclear: for DST-aware
|
||||
classes, one hour per year has two spellings in local time, and
|
||||
another hour has no spelling in local time.] XXX
|
||||
without any conversion of date or time fields. Else \code{self.tzinfo}
|
||||
and \var{tz} must implement the \method{utcoffset()} and \method{dst()}
|
||||
\class{tzinfo} methods, and the date and time fields are adjusted so
|
||||
that the result is local time in time zone \var{tz}, representing the
|
||||
same UTC time as \var{self}: after \code{astz = dt.astimezone(tz)},
|
||||
\code{astz - astz.utcoffset()} will usually have the same date and time
|
||||
members as \code{dt - dt.utcoffset()}. The discussion of class
|
||||
\class{tzinfo} explains the cases at Daylight Saving Time
|
||||
transition boundaries where this cannot be achieved (an issue only if
|
||||
\var{tz} models both standard and daylight time).
|
||||
\end{methoddesc}
|
||||
|
||||
\begin{methoddesc}{utcoffset}{}
|
||||
|
|
|
@ -50,6 +50,12 @@ Extension modules
|
|||
time), this case can arise one hour per year, at the hour daylight time
|
||||
ends. See new docs for details.
|
||||
|
||||
The constructors building a datetime from a timestamp could raise
|
||||
ValueError if the platform C localtime()/gmtime() inserted "leap
|
||||
seconds". Leap seconds are ignored now. On such platforms, it's
|
||||
possible to have timestamps that differ by a second, yet where
|
||||
datetimes constructed from them are equal.
|
||||
|
||||
Library
|
||||
-------
|
||||
|
||||
|
|
|
@ -2831,7 +2831,15 @@ datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us)
|
|||
PyObject *result = NULL;
|
||||
|
||||
tm = f(&timet);
|
||||
if (tm)
|
||||
if (tm) {
|
||||
/* The platform localtime/gmtime may insert leap seconds,
|
||||
* indicated by tm->tm_sec > 59. We don't care about them,
|
||||
* except to the extent that passing them on to the datetime
|
||||
* constructor would raise ValueError for a reason that
|
||||
* made no sense to the user.
|
||||
*/
|
||||
if (tm->tm_sec > 59)
|
||||
tm->tm_sec = 59;
|
||||
result = PyObject_CallFunction(cls, "iiiiiii",
|
||||
tm->tm_year + 1900,
|
||||
tm->tm_mon + 1,
|
||||
|
@ -2840,6 +2848,7 @@ datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us)
|
|||
tm->tm_min,
|
||||
tm->tm_sec,
|
||||
us);
|
||||
}
|
||||
else
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"timestamp out of range for "
|
||||
|
|
Loading…
Reference in New Issue