mirror of
https://github.com/python/cpython.git
synced 2024-11-24 18:34:43 +08:00
astimezone() internals: if utcoffset() returns a duration, complain if
dst() returns None (instead of treating that as 0).
This commit is contained in:
parent
0123139d66
commit
710fb1548a
@ -893,20 +893,13 @@ implement all of them.
|
|||||||
return CONSTANT # fixed-offset class
|
return CONSTANT # fixed-offset class
|
||||||
return CONSTANT + self.dst(dt) # daylight-aware class
|
return CONSTANT + self.dst(dt) # daylight-aware class
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
|
|
||||||
|
If \method{utcoffset()} does not return \code{None},
|
||||||
|
\method{dst()} should not return \code{None} either.
|
||||||
|
|
||||||
|
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
|
||||||
\begin{methoddesc}{tzname}{self, dt}
|
|
||||||
Return the timezone name corresponding to the \class{datetime} represented
|
|
||||||
by \var{dt}, as a string. Nothing about string names is defined by the
|
|
||||||
\module{datetime} module, and there's no requirement that it mean anything
|
|
||||||
in particular. For example, "GMT", "UTC", "-500", "-5:00", "EDT",
|
|
||||||
"US/Eastern", "America/New York" are all valid replies. Return
|
|
||||||
\code{None} if a string name isn't known. Note that this is a method
|
|
||||||
rather than a fixed string primarily because some \class{tzinfo} objects
|
|
||||||
will wish to return different names depending on the specific value
|
|
||||||
of \var{dt} passed, especially if the \class{tzinfo} class is
|
|
||||||
accounting for daylight time.
|
|
||||||
\end{methoddesc}
|
|
||||||
|
|
||||||
\begin{methoddesc}{dst}{self, dt}
|
\begin{methoddesc}{dst}{self, dt}
|
||||||
Return the daylight savings time (DST) adjustment, in minutes east of
|
Return the daylight savings time (DST) adjustment, in minutes east of
|
||||||
@ -937,6 +930,19 @@ implement all of them.
|
|||||||
but cannot detect violations; it's the programmer's responsibility to
|
but cannot detect violations; it's the programmer's responsibility to
|
||||||
ensure it.
|
ensure it.
|
||||||
|
|
||||||
|
\begin{methoddesc}{tzname}{self, dt}
|
||||||
|
Return the timezone name corresponding to the \class{datetime} represented
|
||||||
|
by \var{dt}, as a string. Nothing about string names is defined by the
|
||||||
|
\module{datetime} module, and there's no requirement that it mean anything
|
||||||
|
in particular. For example, "GMT", "UTC", "-500", "-5:00", "EDT",
|
||||||
|
"US/Eastern", "America/New York" are all valid replies. Return
|
||||||
|
\code{None} if a string name isn't known. Note that this is a method
|
||||||
|
rather than a fixed string primarily because some \class{tzinfo} objects
|
||||||
|
will wish to return different names depending on the specific value
|
||||||
|
of \var{dt} passed, especially if the \class{tzinfo} class is
|
||||||
|
accounting for daylight time.
|
||||||
|
\end{methoddesc}
|
||||||
|
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
|
||||||
These methods are called by a \class{datetimetz} or \class{timetz} object,
|
These methods are called by a \class{datetimetz} or \class{timetz} object,
|
||||||
@ -1379,7 +1385,7 @@ Instance methods:
|
|||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
>>> from datetime import *
|
>>> from datetime import *
|
||||||
>>> class TZ(tzinfo):
|
>>> class TZ(tzinfo):
|
||||||
... def utcoffset(self, dt): return -399
|
... def utcoffset(self, dt): return timedelta(minutes=-399)
|
||||||
...
|
...
|
||||||
>>> datetimetz(2002, 12, 25, tzinfo=TZ()).isoformat(' ')
|
>>> datetimetz(2002, 12, 25, tzinfo=TZ()).isoformat(' ')
|
||||||
'2002-12-25 00:00:00-06:39'
|
'2002-12-25 00:00:00-06:39'
|
||||||
|
@ -2591,6 +2591,8 @@ class TestTimezoneConversions(unittest.TestCase):
|
|||||||
dston = datetimetz(2002, 4, 7, 2)
|
dston = datetimetz(2002, 4, 7, 2)
|
||||||
dstoff = datetimetz(2002, 10, 27, 2)
|
dstoff = datetimetz(2002, 10, 27, 2)
|
||||||
|
|
||||||
|
theclass = datetimetz
|
||||||
|
|
||||||
# Check a time that's inside DST.
|
# Check a time that's inside DST.
|
||||||
def checkinside(self, dt, tz, utc, dston, dstoff):
|
def checkinside(self, dt, tz, utc, dston, dstoff):
|
||||||
self.assertEqual(dt.dst(), HOUR)
|
self.assertEqual(dt.dst(), HOUR)
|
||||||
@ -2729,6 +2731,21 @@ class TestTimezoneConversions(unittest.TestCase):
|
|||||||
got = sixutc.astimezone(Eastern).astimezone(None)
|
got = sixutc.astimezone(Eastern).astimezone(None)
|
||||||
self.assertEqual(expected, got)
|
self.assertEqual(expected, got)
|
||||||
|
|
||||||
|
def test_bogus_dst(self):
|
||||||
|
class ok(tzinfo):
|
||||||
|
def utcoffset(self, dt): return HOUR
|
||||||
|
def dst(self, dt): return HOUR
|
||||||
|
|
||||||
|
now = self.theclass.now().replace(tzinfo=utc_real)
|
||||||
|
# Doesn't blow up.
|
||||||
|
now.astimezone(ok())
|
||||||
|
|
||||||
|
# Does blow up.
|
||||||
|
class notok(ok):
|
||||||
|
def dst(self, dt): return None
|
||||||
|
self.assertRaises(ValueError, now.astimezone, notok())
|
||||||
|
|
||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
allsuites = [unittest.makeSuite(klass, 'test')
|
allsuites = [unittest.makeSuite(klass, 'test')
|
||||||
for klass in (TestModule,
|
for klass in (TestModule,
|
||||||
|
@ -22,6 +22,10 @@ Extension modules
|
|||||||
today() and now() now round system timestamps to the closest
|
today() and now() now round system timestamps to the closest
|
||||||
microsecond <http://www.python.org/sf/661086>.
|
microsecond <http://www.python.org/sf/661086>.
|
||||||
|
|
||||||
|
In dt.asdatetime(tz), if tz.utcoffset(dt) returns a duration,
|
||||||
|
ValueError is raised of tz.dst(dt) returns None (2.3a1 treated it
|
||||||
|
as 0 instead).
|
||||||
|
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
@ -4805,7 +4805,11 @@ datetimetz_astimezone(PyDateTime_DateTimeTZ *self, PyObject *args,
|
|||||||
resdst = call_dst(tzinfo, result, &none);
|
resdst = call_dst(tzinfo, result, &none);
|
||||||
if (resdst == -1 && PyErr_Occurred())
|
if (resdst == -1 && PyErr_Occurred())
|
||||||
goto Fail;
|
goto Fail;
|
||||||
/* None and 0 dst() results are the same to us here. Debatable. */
|
if (none) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "astimezone(): utcoffset() "
|
||||||
|
"returned a duration but dst() returned None");
|
||||||
|
goto Fail;
|
||||||
|
}
|
||||||
total_added_to_result = resoff - resdst - selfoff;
|
total_added_to_result = resoff - resdst - selfoff;
|
||||||
if (total_added_to_result != 0) {
|
if (total_added_to_result != 0) {
|
||||||
mm += total_added_to_result;
|
mm += total_added_to_result;
|
||||||
|
Loading…
Reference in New Issue
Block a user