Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 75a6e3b

Browse files
committed
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().
1 parent 85e4c67 commit 75a6e3b

3 files changed

Lines changed: 50 additions & 21 deletions

File tree

Doc/lib/libdatetime.tex

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,9 @@ \subsection{\class{date} Objects \label{datetime-date}}
314314
\exception{ValueError}, if the timestamp is out of the range of
315315
values supported by the platform C \cfunction{localtime()}
316316
function. It's common for this to be restricted to years from 1970
317-
through 2038.
318-
\end{methoddesc}
317+
through 2038. Note that on non-POSIX systems that include leap
318+
seconds in their notion of a timestamp, leap seconds are ignored by
319+
\method{fromtimestamp()}.
319320

320321
\begin{methoddesc}{fromordinal}{ordinal}
321322
Return the date corresponding to the proleptic Gregorian ordinal,
@@ -546,6 +547,11 @@ \subsection{\class{datetime} Objects \label{datetime-datetime}}
546547
range of values supported by the platform C
547548
\cfunction{localtime()} function. It's common for this to be
548549
restricted to years in 1970 through 2038.
550+
Note that on non-POSIX systems that include leap seconds in their
551+
notion of a timestamp, leap seconds are ignored by
552+
\method{fromtimestamp()}, and then it's possible to have two timestamps
553+
differing by a second that yield identical \class{datetime} objects.
554+
\end{methoddesc}
549555
See also \method{utcfromtimestamp()}.
550556
\end{methoddesc}
551557

@@ -988,28 +994,31 @@ \subsection{\class{tzinfo} Objects \label{datetime-tzinfo}}
988994

989995
When DST starts (the "start" line), the local wall clock leaps from 1:59
990996
to 3:00. A wall time of the form 2:MM doesn't really make sense on that
991-
day, so astimezone(Eastern) won't deliver a result with hour=2 on the
992-
day DST begins. How an Eastern class chooses to interpret 2:MM on
993-
that day is its business. The example Eastern class above chose to
997+
day, so \code{astimezone(Eastern)} won't deliver a result with
998+
\code{hour==2} on the
999+
day DST begins. How an Eastern instance chooses to interpret 2:MM on
1000+
that day is its business. The example Eastern implementation above
1001+
chose to
9941002
consider it as a time in EDT, simply because it "looks like it's
9951003
after 2:00", and so synonymous with the EST 1:MM times on that day.
9961004
Your Eastern class may wish, for example, to raise an exception instead
997-
when it sees a 2:MM time on the day Eastern begins.
1005+
when it sees a 2:MM time on the day EDT begins.
9981006

9991007
When DST ends (the "end" line), there's a potentially worse problem:
1000-
there's an hour that can't be spelled at all in local wall time, the
1008+
there's an hour that can't be spelled unambiguously in local wall time, the
10011009
hour beginning at the moment DST ends. In this example, that's times of
10021010
the form 6:MM UTC on the day daylight time ends. The local wall clock
10031011
leaps from 1:59 (daylight time) back to 1:00 (standard time) again.
10041012
1:MM is taken as daylight time (it's "before 2:00"), so maps to 5:MM UTC.
10051013
2:MM is taken as standard time (it's "after 2:00"), so maps to 7:MM UTC.
10061014
There is no local time that maps to 6:MM UTC on this day.
10071015

1008-
Just as the wall clock does, astimezone(Eastern) maps both UTC hours 5:MM
1016+
Just as the wall clock does, \code{astimezone(Eastern)} maps both UTC
1017+
hours 5:MM
10091018
and 6:MM to Eastern hour 1:MM on this day. However, this result is
10101019
ambiguous (there's no way for Eastern to know which repetition of 1:MM
1011-
is intended). Applications that can't bear such ambiguity even one hour
1012-
per year should avoid using hybrid tzinfo classes; there are no
1020+
is intended). Applications that can't bear such ambiguity
1021+
should avoid using hybrid tzinfo classes; there are no
10131022
ambiguities when using UTC, or any other fixed-offset tzinfo subclass
10141023
(such as a class representing only EST (fixed offset -5 hours), or only
10151024
EDT (fixed offset -4 hours)).
@@ -1354,19 +1363,24 @@ \subsection{ \class{datetimetz} Objects \label{datetime-datetimetz}}
13541363
\end{methoddesc}
13551364

13561365
\begin{methoddesc}{astimezone}{tz}
1357-
Return a \class{datetimetz} with new tzinfo member \var{tz}. \var{tz}
1358-
must be \code{None}, or an instance of a \class{tzinfo} subclass. If
1359-
\var{tz} is \code{None}, self is naive, or
1366+
Return a \class{datetimetz} object with new \membar{tzinfo} member
1367+
\var{tz}.
1368+
\var{tz} must be \code{None}, or an instance of a \class{tzinfo} subclass.
1369+
If \var{tz} is \code{None}, \var{self} is naive,
13601370
\code{tz.utcoffset(self)} returns \code{None},
1371+
or \code{self.tzinfo}\ is \var{tz},
13611372
\code{self.astimezone(tz)} is equivalent to
13621373
\code{self.replace(tzinfo=tz)}: a new timezone object is attached
1363-
without any conversion of date or time fields. If self is aware and
1364-
\code{tz.utcoffset(self)} does not return \code{None}, the date and
1365-
time fields are adjusted so that the result is local time in timezone
1366-
tz, representing the same UTC time as self.
1367-
XXX [The treatment of endcases remains unclear: for DST-aware
1368-
classes, one hour per year has two spellings in local time, and
1369-
another hour has no spelling in local time.] XXX
1374+
without any conversion of date or time fields. Else \code{self.tzinfo}
1375+
and \var{tz} must implement the \method{utcoffset()} and \method{dst()}
1376+
\class{tzinfo} methods, and the date and time fields are adjusted so
1377+
that the result is local time in time zone \var{tz}, representing the
1378+
same UTC time as \var{self}: after \code{astz = dt.astimezone(tz)},
1379+
\code{astz - astz.utcoffset()} will usually have the same date and time
1380+
members as \code{dt - dt.utcoffset()}. The discussion of class
1381+
\class{tzinfo} explains the cases at Daylight Saving Time
1382+
transition boundaries where this cannot be achieved (an issue only if
1383+
\var{tz} models both standard and daylight time).
13701384
\end{methoddesc}
13711385

13721386
\begin{methoddesc}{utcoffset}{}

Misc/NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ Extension modules
5050
time), this case can arise one hour per year, at the hour daylight time
5151
ends. See new docs for details.
5252

53+
The constructors building a datetime from a timestamp could raise
54+
ValueError if the platform C localtime()/gmtime() inserted "leap
55+
seconds". Leap seconds are ignored now. On such platforms, it's
56+
possible to have timestamps that differ by a second, yet where
57+
datetimes constructed from them are equal.
58+
5359
Library
5460
-------
5561

Modules/datetimemodule.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2831,7 +2831,15 @@ datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us)
28312831
PyObject *result = NULL;
28322832

28332833
tm = f(&timet);
2834-
if (tm)
2834+
if (tm) {
2835+
/* The platform localtime/gmtime may insert leap seconds,
2836+
* indicated by tm->tm_sec > 59. We don't care about them,
2837+
* except to the extent that passing them on to the datetime
2838+
* constructor would raise ValueError for a reason that
2839+
* made no sense to the user.
2840+
*/
2841+
if (tm->tm_sec > 59)
2842+
tm->tm_sec = 59;
28352843
result = PyObject_CallFunction(cls, "iiiiiii",
28362844
tm->tm_year + 1900,
28372845
tm->tm_mon + 1,
@@ -2840,6 +2848,7 @@ datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us)
28402848
tm->tm_min,
28412849
tm->tm_sec,
28422850
us);
2851+
}
28432852
else
28442853
PyErr_SetString(PyExc_ValueError,
28452854
"timestamp out of range for "

0 commit comments

Comments
 (0)