mirror of
https://github.com/python/cpython.git
synced 2025-10-13 18:33:34 +00:00
A step on the way to making tzinfo classes writable by mortals: get rid
of the timetz case. A tzinfo method will always see a datetimetz arg, or None, now. In the former case, it's still possible that it will get a datetimetz argument belonging to a different timezone. That will get fixed next.
This commit is contained in:
parent
567332abc4
commit
bad8ff089a
3 changed files with 116 additions and 65 deletions
|
@ -1,5 +1,5 @@
|
||||||
% XXX what order should the types be discussed in?
|
% XXX what order should the types be discussed in?
|
||||||
|
|
||||||
\section{\module{datetime} ---
|
\section{\module{datetime} ---
|
||||||
Basic date and time types}
|
Basic date and time types}
|
||||||
|
|
||||||
|
@ -785,13 +785,13 @@ Instance attributes (read-only):
|
||||||
\begin{memberdesc}{hour}
|
\begin{memberdesc}{hour}
|
||||||
In \code{range(24)}.
|
In \code{range(24)}.
|
||||||
\end{memberdesc}
|
\end{memberdesc}
|
||||||
\begin{memberdesc}{minute}
|
\begin{memberdesc}{minute}
|
||||||
In \code{range(60)}.
|
In \code{range(60)}.
|
||||||
\end{memberdesc}
|
\end{memberdesc}
|
||||||
\begin{memberdesc}{second}
|
\begin{memberdesc}{second}
|
||||||
In \code{range(60)}.
|
In \code{range(60)}.
|
||||||
\end{memberdesc}
|
\end{memberdesc}
|
||||||
\begin{memberdesc}{microsecond}
|
\begin{memberdesc}{microsecond}
|
||||||
In \code{range(1000000)}.
|
In \code{range(1000000)}.
|
||||||
\end{memberdesc}
|
\end{memberdesc}
|
||||||
|
|
||||||
|
@ -844,7 +844,7 @@ Instance methods:
|
||||||
should not be instantiated directly. You need to derive a concrete
|
should not be instantiated directly. You need to derive a concrete
|
||||||
subclass, and (at least) supply implementations of the standard
|
subclass, and (at least) supply implementations of the standard
|
||||||
\class{tzinfo} methods needed by the \class{datetime} methods you
|
\class{tzinfo} methods needed by the \class{datetime} methods you
|
||||||
use. The \module{datetime} module does not supply any concrete
|
use. The \module{datetime} module does not supply any concrete
|
||||||
subclasses of \class{tzinfo}.
|
subclasses of \class{tzinfo}.
|
||||||
|
|
||||||
An instance of (a concrete subclass of) \class{tzinfo} can be passed
|
An instance of (a concrete subclass of) \class{tzinfo} can be passed
|
||||||
|
@ -854,21 +854,17 @@ The latter objects view their fields as being in local time, and the
|
||||||
from UTC, the name of the time zone, and DST offset, all relative to a
|
from UTC, the name of the time zone, and DST offset, all relative to a
|
||||||
date or time object passed to them.
|
date or time object passed to them.
|
||||||
|
|
||||||
Special requirement for pickling: A tzinfo subclass must have an
|
Special requirement for pickling: A \class{tzinfo} subclass must have an
|
||||||
\method{__init__} method that can be called with no arguments, else it
|
\method{__init__} method that can be called with no arguments, else it
|
||||||
can be pickled but possibly not unpickled again. This is a technical
|
can be pickled but possibly not unpickled again. This is a technical
|
||||||
requirement that may be relaxed in the future.
|
requirement that may be relaxed in the future.
|
||||||
|
|
||||||
A concrete subclass of \class{tzinfo} may need to implement the
|
A concrete subclass of \class{tzinfo} may need to implement the
|
||||||
following methods. Exactly which methods are needed depends on the
|
following methods. Exactly which methods are needed depends on the
|
||||||
uses made of aware \module{datetime} objects; if in doubt, simply
|
uses made of aware \module{datetime} objects. If in doubt, simply
|
||||||
implement all of them. The methods are called by a \class{datetimetz}
|
implement all of them.
|
||||||
or \class{timetz} object, passing itself as the argument. A
|
|
||||||
\class{tzinfo} subclass's methods should be prepared to accept a dt
|
|
||||||
argument of \code{None} or of type \class{timetz} or
|
|
||||||
\class{datetimetz}.
|
|
||||||
|
|
||||||
\begin{methoddesc}{utcoffset}{dt}
|
\begin{methoddesc}{utcoffset}{self, dt}
|
||||||
Return offset of local time from UTC, in minutes east of UTC. If
|
Return offset of local time from UTC, in minutes east of UTC. If
|
||||||
local time is west of UTC, this should be negative. Note that this
|
local time is west of UTC, this should be negative. Note that this
|
||||||
is intended to be the total offset from UTC; for example, if a
|
is intended to be the total offset from UTC; for example, if a
|
||||||
|
@ -878,10 +874,14 @@ argument of \code{None} or of type \class{timetz} or
|
||||||
an integer, in the range -1439 to 1439 inclusive (1440 = 24*60;
|
an integer, in the range -1439 to 1439 inclusive (1440 = 24*60;
|
||||||
the magnitude of the offset must be less than one day), or a
|
the magnitude of the offset must be less than one day), or a
|
||||||
\class{timedelta} object representing a whole number of minutes
|
\class{timedelta} object representing a whole number of minutes
|
||||||
in the same range.
|
in the same range. Most implementations of \method{utcoffset()}
|
||||||
|
will probably look like:
|
||||||
|
\begin{verbatim}
|
||||||
|
return CONSTANT # fixed-offset class
|
||||||
|
return CONSTANT + self.dst(dt) # daylight-aware class
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
|
||||||
\begin{methoddesc}{tzname}{dt}
|
\begin{methoddesc}{tzname}{self, dt}
|
||||||
Return the timezone name corresponding to the \class{datetime} represented
|
Return the timezone name corresponding to the \class{datetime} represented
|
||||||
by dt, as a string. Nothing about string names is defined by the
|
by dt, as a string. Nothing about string names is defined by the
|
||||||
\module{datetime} module, and there's no requirement that it mean anything
|
\module{datetime} module, and there's no requirement that it mean anything
|
||||||
|
@ -893,7 +893,7 @@ argument of \code{None} or of type \class{timetz} or
|
||||||
of dt passed, especially if the \class{tzinfo} class is accounting for DST.
|
of dt passed, especially if the \class{tzinfo} class is accounting for DST.
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
|
||||||
\begin{methoddesc}{dst}{dt}
|
\begin{methoddesc}{dst}{self, dt}
|
||||||
Return the DST offset, in minutes east of UTC, or \code{None} if
|
Return the DST offset, in minutes east of UTC, or \code{None} if
|
||||||
DST information isn't known. Return 0 if DST is not in effect.
|
DST information isn't known. Return 0 if DST is not in effect.
|
||||||
If DST is in effect, return the offset as an integer or
|
If DST is in effect, return the offset as an integer or
|
||||||
|
@ -907,6 +907,26 @@ argument of \code{None} or of type \class{timetz} or
|
||||||
\member{tm_isdst} flag should be set.
|
\member{tm_isdst} flag should be set.
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
|
||||||
|
These methods are called by a \class{datetimetz} or \class{timetz} object,
|
||||||
|
in response to their methods of the same names. A \class{datetimetz}
|
||||||
|
object passes itself as the argument, and a \class{timetz} object passes
|
||||||
|
\code{None} as the argument. A \class{tzinfo} subclass's methods should
|
||||||
|
therefore be prepared to accept a \var{dt} argument of \code{None}, or of
|
||||||
|
class \class{datetimetz}.
|
||||||
|
|
||||||
|
When \code{None} is passed, it's up to the class designer to decide the
|
||||||
|
best response. For example, returning \code{None} is appropriate if the
|
||||||
|
class wishes to say that timetz objects don't participate in the
|
||||||
|
\class{tzinfo} protocol. In other applications, it may be more useful
|
||||||
|
for \code{utcoffset(None}} to return the standard UTC offset.
|
||||||
|
|
||||||
|
When a \class{datetimetz} object is passed in response to a
|
||||||
|
\class{datetimetz} method, \code{dt.tzinfo} is the same object as
|
||||||
|
\var{self}. \class{tzinfo} methods can rely on this, unless
|
||||||
|
user code calls \class{tzinfo} methods directly. The intent is that
|
||||||
|
the \class{tzinfo} methods interpret \var{dt} as being in local time,
|
||||||
|
and not need to worry about objects in other timezones.
|
||||||
|
|
||||||
Example \class{tzinfo} classes:
|
Example \class{tzinfo} classes:
|
||||||
|
|
||||||
\verbatiminput{tzinfo-examples.py}
|
\verbatiminput{tzinfo-examples.py}
|
||||||
|
|
|
@ -1557,6 +1557,23 @@ class TestTime(unittest.TestCase):
|
||||||
# must be legit (which is true for timetz and datetimetz).
|
# must be legit (which is true for timetz and datetimetz).
|
||||||
class TZInfoBase(unittest.TestCase):
|
class TZInfoBase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_argument_passing(self):
|
||||||
|
cls = self.theclass
|
||||||
|
# A datetimetz passes itself on, a timetz passes None.
|
||||||
|
class introspective(tzinfo):
|
||||||
|
def tzname(self, dt): return dt and "real" or "none"
|
||||||
|
def utcoffset(self, dt): return dt and 42 or -42
|
||||||
|
dst = utcoffset
|
||||||
|
|
||||||
|
obj = cls(1, 2, 3, tzinfo=introspective())
|
||||||
|
|
||||||
|
expected = cls is timetz and "none" or "real"
|
||||||
|
self.assertEqual(obj.tzname(), expected)
|
||||||
|
|
||||||
|
expected = timedelta(minutes=(cls is timetz and -42 or 42))
|
||||||
|
self.assertEqual(obj.utcoffset(), expected)
|
||||||
|
self.assertEqual(obj.dst(), expected)
|
||||||
|
|
||||||
def test_bad_tzinfo_classes(self):
|
def test_bad_tzinfo_classes(self):
|
||||||
cls = self.theclass
|
cls = self.theclass
|
||||||
self.assertRaises(TypeError, cls, 1, 1, 1, tzinfo=12)
|
self.assertRaises(TypeError, cls, 1, 1, 1, tzinfo=12)
|
||||||
|
@ -1677,22 +1694,26 @@ class TZInfoBase(unittest.TestCase):
|
||||||
self.assertEqual(got, expected)
|
self.assertEqual(got, expected)
|
||||||
|
|
||||||
# However, if they're different members, uctoffset is not ignored.
|
# However, if they're different members, uctoffset is not ignored.
|
||||||
d0 = base.replace(minute=3, tzinfo=OperandDependentOffset())
|
# Note that a timetz can't actually have an operand-depedent offset,
|
||||||
d1 = base.replace(minute=9, tzinfo=OperandDependentOffset())
|
# though (and timetz.utcoffset() passes None to tzinfo.utcoffset()),
|
||||||
d2 = base.replace(minute=11, tzinfo=OperandDependentOffset())
|
# so skip this test for timetz.
|
||||||
for x in d0, d1, d2:
|
if cls is not timetz:
|
||||||
for y in d0, d1, d2:
|
d0 = base.replace(minute=3, tzinfo=OperandDependentOffset())
|
||||||
got = cmp(x, y)
|
d1 = base.replace(minute=9, tzinfo=OperandDependentOffset())
|
||||||
if (x is d0 or x is d1) and (y is d0 or y is d1):
|
d2 = base.replace(minute=11, tzinfo=OperandDependentOffset())
|
||||||
expected = 0
|
for x in d0, d1, d2:
|
||||||
elif x is y is d2:
|
for y in d0, d1, d2:
|
||||||
expected = 0
|
got = cmp(x, y)
|
||||||
elif x is d2:
|
if (x is d0 or x is d1) and (y is d0 or y is d1):
|
||||||
expected = -1
|
expected = 0
|
||||||
else:
|
elif x is y is d2:
|
||||||
assert y is d2
|
expected = 0
|
||||||
expected = 1
|
elif x is d2:
|
||||||
self.assertEqual(got, expected)
|
expected = -1
|
||||||
|
else:
|
||||||
|
assert y is d2
|
||||||
|
expected = 1
|
||||||
|
self.assertEqual(got, expected)
|
||||||
|
|
||||||
|
|
||||||
class TestTimeTZ(TestTime, TZInfoBase):
|
class TestTimeTZ(TestTime, TZInfoBase):
|
||||||
|
@ -2535,7 +2556,7 @@ class USTimeZone(tzinfo):
|
||||||
return self.stdoffset + self.dst(dt)
|
return self.stdoffset + self.dst(dt)
|
||||||
|
|
||||||
def dst(self, dt):
|
def dst(self, dt):
|
||||||
if dt is None or isinstance(dt, time) or dt.tzinfo is None:
|
if dt is None or dt.tzinfo is None:
|
||||||
# An exception instead may be sensible here, in one or more of
|
# An exception instead may be sensible here, in one or more of
|
||||||
# the cases.
|
# the cases.
|
||||||
return ZERO
|
return ZERO
|
||||||
|
|
|
@ -564,22 +564,22 @@ check_tzinfo_subclass(PyObject *p)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return tzinfo.methname(self), without any checking of results.
|
/* Return tzinfo.methname(tzinfoarg), without any checking of results.
|
||||||
* If tzinfo is None, returns None.
|
* If tzinfo is None, returns None.
|
||||||
*/
|
*/
|
||||||
static PyObject *
|
static PyObject *
|
||||||
call_tzinfo_method(PyObject *self, PyObject *tzinfo, char *methname)
|
call_tzinfo_method(PyObject *tzinfo, char *methname, PyObject *tzinfoarg)
|
||||||
{
|
{
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
assert(self && tzinfo && methname);
|
assert(tzinfo && methname && tzinfoarg);
|
||||||
assert(check_tzinfo_subclass(tzinfo) >= 0);
|
assert(check_tzinfo_subclass(tzinfo) >= 0);
|
||||||
if (tzinfo == Py_None) {
|
if (tzinfo == Py_None) {
|
||||||
result = Py_None;
|
result = Py_None;
|
||||||
Py_INCREF(result);
|
Py_INCREF(result);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = PyObject_CallMethod(tzinfo, methname, "O", self);
|
result = PyObject_CallMethod(tzinfo, methname, "O", tzinfoarg);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,8 +612,8 @@ replace_tzinfo(PyObject *self, PyObject *newtzinfo)
|
||||||
((PyDateTime_DateTimeTZ *)self)->tzinfo = newtzinfo;
|
((PyDateTime_DateTimeTZ *)self)->tzinfo = newtzinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal helper.
|
|
||||||
* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
|
/* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
|
||||||
* result. tzinfo must be an instance of the tzinfo class. If the method
|
* result. tzinfo must be an instance of the tzinfo class. If the method
|
||||||
* returns None, this returns 0 and sets *none to 1. If the method doesn't
|
* returns None, this returns 0 and sets *none to 1. If the method doesn't
|
||||||
* return a Python int or long or timedelta, TypeError is raised and this
|
* return a Python int or long or timedelta, TypeError is raised and this
|
||||||
|
@ -635,7 +635,7 @@ call_utc_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg,
|
||||||
assert(tzinfoarg != NULL);
|
assert(tzinfoarg != NULL);
|
||||||
|
|
||||||
*none = 0;
|
*none = 0;
|
||||||
u = call_tzinfo_method(tzinfoarg, tzinfo, name);
|
u = call_tzinfo_method(tzinfo, name, tzinfoarg);
|
||||||
if (u == NULL)
|
if (u == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -702,18 +702,21 @@ call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
|
||||||
|
|
||||||
static PyObject *new_delta(int d, int sec, int usec, int normalize);
|
static PyObject *new_delta(int d, int sec, int usec, int normalize);
|
||||||
|
|
||||||
/* Call tzinfo.name(self) and return the offset as a timedelta or None. */
|
/* Call tzinfo.name(tzinfoarg), and return the offset as a timedelta or None.
|
||||||
|
*/
|
||||||
static PyObject *
|
static PyObject *
|
||||||
offset_as_timedelta(PyObject *self, PyObject *tzinfo, char *name) {
|
offset_as_timedelta(PyObject *tzinfo, char *name, PyObject *tzinfoarg) {
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
|
assert(tzinfo && name && tzinfoarg);
|
||||||
if (tzinfo == Py_None) {
|
if (tzinfo == Py_None) {
|
||||||
result = Py_None;
|
result = Py_None;
|
||||||
Py_INCREF(result);
|
Py_INCREF(result);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int none;
|
int none;
|
||||||
int offset = call_utc_tzinfo_method(tzinfo, name, self, &none);
|
int offset = call_utc_tzinfo_method(tzinfo, name, tzinfoarg,
|
||||||
|
&none);
|
||||||
if (offset < 0 && PyErr_Occurred())
|
if (offset < 0 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
if (none) {
|
if (none) {
|
||||||
|
@ -740,26 +743,26 @@ call_dst(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
|
||||||
return call_utc_tzinfo_method(tzinfo, "dst", tzinfoarg, none);
|
return call_utc_tzinfo_method(tzinfo, "dst", tzinfoarg, none);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call tzinfo.tzname(self), and return the result. tzinfo must be
|
/* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be
|
||||||
* an instance of the tzinfo class or None. If tzinfo isn't None, and
|
* an instance of the tzinfo class or None. If tzinfo isn't None, and
|
||||||
* tzname() doesn't return None ora string, TypeError is raised and this
|
* tzname() doesn't return None or a string, TypeError is raised and this
|
||||||
* returns NULL.
|
* returns NULL.
|
||||||
*/
|
*/
|
||||||
static PyObject *
|
static PyObject *
|
||||||
call_tzname(PyObject *self, PyObject *tzinfo)
|
call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
|
||||||
{
|
{
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
assert(self != NULL);
|
|
||||||
assert(tzinfo != NULL);
|
assert(tzinfo != NULL);
|
||||||
assert(check_tzinfo_subclass(tzinfo) >= 0);
|
assert(check_tzinfo_subclass(tzinfo) >= 0);
|
||||||
|
assert(tzinfoarg != NULL);
|
||||||
|
|
||||||
if (tzinfo == Py_None) {
|
if (tzinfo == Py_None) {
|
||||||
result = Py_None;
|
result = Py_None;
|
||||||
Py_INCREF(result);
|
Py_INCREF(result);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = PyObject_CallMethod(tzinfo, "tzname", "O", self);
|
result = PyObject_CallMethod(tzinfo, "tzname", "O", tzinfoarg);
|
||||||
|
|
||||||
if (result != NULL && result != Py_None && ! PyString_Check(result)) {
|
if (result != NULL && result != Py_None && ! PyString_Check(result)) {
|
||||||
PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must "
|
PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must "
|
||||||
|
@ -816,7 +819,9 @@ classify_utcoffset(PyObject *op, int *offset)
|
||||||
return (PyTime_Check(op) || PyDate_Check(op)) ?
|
return (PyTime_Check(op) || PyDate_Check(op)) ?
|
||||||
OFFSET_NAIVE : OFFSET_UNKNOWN;
|
OFFSET_NAIVE : OFFSET_UNKNOWN;
|
||||||
}
|
}
|
||||||
*offset = call_utcoffset(tzinfo, op, &none);
|
*offset = call_utcoffset(tzinfo,
|
||||||
|
PyTimeTZ_Check(op) ? Py_None : op,
|
||||||
|
&none);
|
||||||
if (*offset == -1 && PyErr_Occurred())
|
if (*offset == -1 && PyErr_Occurred())
|
||||||
return OFFSET_ERROR;
|
return OFFSET_ERROR;
|
||||||
return none ? OFFSET_NAIVE : OFFSET_AWARE;
|
return none ? OFFSET_NAIVE : OFFSET_AWARE;
|
||||||
|
@ -951,9 +956,12 @@ format_utcoffset(char *buf, size_t buflen, const char *sep,
|
||||||
* so this imports the module and calls it. All the hair is due to
|
* so this imports the module and calls it. All the hair is due to
|
||||||
* giving special meanings to the %z and %Z format codes via a preprocessing
|
* giving special meanings to the %z and %Z format codes via a preprocessing
|
||||||
* step on the format string.
|
* step on the format string.
|
||||||
|
* tzinfoarg is the argument to pass to the object's tzinfo method, if
|
||||||
|
* needed.
|
||||||
*/
|
*/
|
||||||
static PyObject *
|
static PyObject *
|
||||||
wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple)
|
wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
|
||||||
|
PyObject *tzinfoarg)
|
||||||
{
|
{
|
||||||
PyObject *result = NULL; /* guilty until proved innocent */
|
PyObject *result = NULL; /* guilty until proved innocent */
|
||||||
|
|
||||||
|
@ -1031,11 +1039,12 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple)
|
||||||
zreplacement = PyString_FromString("");
|
zreplacement = PyString_FromString("");
|
||||||
if (zreplacement == NULL) goto Done;
|
if (zreplacement == NULL) goto Done;
|
||||||
if (tzinfo != Py_None && tzinfo != NULL) {
|
if (tzinfo != Py_None && tzinfo != NULL) {
|
||||||
|
assert(tzinfoarg != NULL);
|
||||||
if (format_utcoffset(buf,
|
if (format_utcoffset(buf,
|
||||||
sizeof(buf),
|
sizeof(buf),
|
||||||
"",
|
"",
|
||||||
tzinfo,
|
tzinfo,
|
||||||
object) < 0)
|
tzinfoarg) < 0)
|
||||||
goto Done;
|
goto Done;
|
||||||
Py_DECREF(zreplacement);
|
Py_DECREF(zreplacement);
|
||||||
zreplacement = PyString_FromString(buf);
|
zreplacement = PyString_FromString(buf);
|
||||||
|
@ -1053,8 +1062,9 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple)
|
||||||
Zreplacement = PyString_FromString("");
|
Zreplacement = PyString_FromString("");
|
||||||
if (Zreplacement == NULL) goto Done;
|
if (Zreplacement == NULL) goto Done;
|
||||||
if (tzinfo != Py_None && tzinfo != NULL) {
|
if (tzinfo != Py_None && tzinfo != NULL) {
|
||||||
PyObject *temp = call_tzname(object,
|
PyObject *temp;
|
||||||
tzinfo);
|
assert(tzinfoarg != NULL);
|
||||||
|
temp = call_tzname(tzinfo, tzinfoarg);
|
||||||
if (temp == NULL) goto Done;
|
if (temp == NULL) goto Done;
|
||||||
if (temp != Py_None) {
|
if (temp != Py_None) {
|
||||||
assert(PyString_Check(temp));
|
assert(PyString_Check(temp));
|
||||||
|
@ -2424,7 +2434,8 @@ date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
|
||||||
tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
|
tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
|
||||||
if (tuple == NULL)
|
if (tuple == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
result = wrap_strftime((PyObject *)self, format, tuple);
|
result = wrap_strftime((PyObject *)self, format, tuple,
|
||||||
|
(PyObject *)self);
|
||||||
Py_DECREF(tuple);
|
Py_DECREF(tuple);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -3652,7 +3663,7 @@ time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
|
||||||
if (tuple == NULL)
|
if (tuple == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
assert(PyTuple_Size(tuple) == 9);
|
assert(PyTuple_Size(tuple) == 9);
|
||||||
result = wrap_strftime((PyObject *)self, format, tuple);
|
result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
|
||||||
Py_DECREF(tuple);
|
Py_DECREF(tuple);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -4140,18 +4151,17 @@ timetz_dealloc(PyDateTime_TimeTZ *self)
|
||||||
/* These are all METH_NOARGS, so don't need to check the arglist. */
|
/* These are all METH_NOARGS, so don't need to check the arglist. */
|
||||||
static PyObject *
|
static PyObject *
|
||||||
timetz_utcoffset(PyDateTime_TimeTZ *self, PyObject *unused) {
|
timetz_utcoffset(PyDateTime_TimeTZ *self, PyObject *unused) {
|
||||||
return offset_as_timedelta((PyObject *)self, self->tzinfo,
|
return offset_as_timedelta(self->tzinfo, "utcoffset", Py_None);
|
||||||
"utcoffset");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
timetz_dst(PyDateTime_TimeTZ *self, PyObject *unused) {
|
timetz_dst(PyDateTime_TimeTZ *self, PyObject *unused) {
|
||||||
return offset_as_timedelta((PyObject *)self, self->tzinfo, "dst");
|
return offset_as_timedelta(self->tzinfo, "dst", Py_None);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
timetz_tzname(PyDateTime_TimeTZ *self, PyObject *unused) {
|
timetz_tzname(PyDateTime_TimeTZ *self, PyObject *unused) {
|
||||||
return call_tzname((PyObject *)self, self->tzinfo);
|
return call_tzname(self->tzinfo, Py_None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4181,7 +4191,7 @@ timetz_isoformat(PyDateTime_TimeTZ *self)
|
||||||
|
|
||||||
/* We need to append the UTC offset. */
|
/* We need to append the UTC offset. */
|
||||||
if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
|
if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
|
||||||
(PyObject *)self) < 0) {
|
Py_None) < 0) {
|
||||||
Py_DECREF(result);
|
Py_DECREF(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -4234,7 +4244,7 @@ timetz_nonzero(PyDateTime_TimeTZ *self)
|
||||||
}
|
}
|
||||||
offset = 0;
|
offset = 0;
|
||||||
if (self->tzinfo != Py_None) {
|
if (self->tzinfo != Py_None) {
|
||||||
offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
|
offset = call_utcoffset(self->tzinfo, Py_None, &none);
|
||||||
if (offset == -1 && PyErr_Occurred())
|
if (offset == -1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -4543,18 +4553,18 @@ datetimetz_dealloc(PyDateTime_DateTimeTZ *self)
|
||||||
/* These are all METH_NOARGS, so don't need to check the arglist. */
|
/* These are all METH_NOARGS, so don't need to check the arglist. */
|
||||||
static PyObject *
|
static PyObject *
|
||||||
datetimetz_utcoffset(PyDateTime_DateTimeTZ *self, PyObject *unused) {
|
datetimetz_utcoffset(PyDateTime_DateTimeTZ *self, PyObject *unused) {
|
||||||
return offset_as_timedelta((PyObject *)self, self->tzinfo,
|
return offset_as_timedelta(self->tzinfo, "utcoffset",
|
||||||
"utcoffset");
|
(PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
datetimetz_dst(PyDateTime_DateTimeTZ *self, PyObject *unused) {
|
datetimetz_dst(PyDateTime_DateTimeTZ *self, PyObject *unused) {
|
||||||
return offset_as_timedelta((PyObject *)self, self->tzinfo, "dst");
|
return offset_as_timedelta(self->tzinfo, "dst", (PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
datetimetz_tzname(PyDateTime_DateTimeTZ *self, PyObject *unused) {
|
datetimetz_tzname(PyDateTime_DateTimeTZ *self, PyObject *unused) {
|
||||||
return call_tzname((PyObject *)self, self->tzinfo);
|
return call_tzname(self->tzinfo, (PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue