Kaydet (Commit) 37f39828 authored tarafından Tim Peters's avatar Tim Peters

Got rid of the timetz type entirely. This was a bit trickier than I

hoped it would be, but not too bad.  A test had to change:
time.__setstate__() can no longer add a non-None tzinfo member to a time
object that didn't already have one, since storage for a tzinfo member
doesn't exist in that case.
üst a5e8bb94
...@@ -27,6 +27,11 @@ ...@@ -27,6 +27,11 @@
/* # of bytes for year, month, day, hour, minute, second, and usecond. */ /* # of bytes for year, month, day, hour, minute, second, and usecond. */
#define _PyDateTime_DATETIME_DATASIZE 10 #define _PyDateTime_DATETIME_DATASIZE 10
#define _PyTZINFO_HEAD \
PyObject_HEAD \
long hashcode; \
char hastzinfo; /* boolean flag */
typedef struct typedef struct
{ {
PyObject_HEAD PyObject_HEAD
...@@ -49,20 +54,23 @@ typedef struct ...@@ -49,20 +54,23 @@ typedef struct
PyObject *tzinfo; PyObject *tzinfo;
} PyDateTime_DateTimeTZ; } PyDateTime_DateTimeTZ;
#define _PyDateTime_TIMEHEAD \
_PyTZINFO_HEAD \
unsigned char data[_PyDateTime_TIME_DATASIZE];
typedef struct typedef struct
{ {
PyObject_HEAD _PyDateTime_TIMEHEAD
long hashcode; } _PyDateTime_BaseTime; /* hastzinfo false */
unsigned char data[_PyDateTime_TIME_DATASIZE];
} PyDateTime_Time;
typedef struct typedef struct
{ {
PyObject_HEAD _PyDateTime_TIMEHEAD
long hashcode;
unsigned char data[_PyDateTime_TIME_DATASIZE];
PyObject *tzinfo; PyObject *tzinfo;
} PyDateTime_TimeTZ; } PyDateTime_Time; /* hastzinfo true */
typedef struct typedef struct
{ {
...@@ -92,7 +100,7 @@ typedef struct ...@@ -92,7 +100,7 @@ typedef struct
(((PyDateTime_DateTime*)o)->data[8] << 8) | \ (((PyDateTime_DateTime*)o)->data[8] << 8) | \
((PyDateTime_DateTime*)o)->data[9]) ((PyDateTime_DateTime*)o)->data[9])
/* Apply for time and timetz instances. */ /* Apply for time instances. */
#define PyDateTime_TIME_GET_HOUR(o) (((PyDateTime_Time*)o)->data[0]) #define PyDateTime_TIME_GET_HOUR(o) (((PyDateTime_Time*)o)->data[0])
#define PyDateTime_TIME_GET_MINUTE(o) (((PyDateTime_Time*)o)->data[1]) #define PyDateTime_TIME_GET_MINUTE(o) (((PyDateTime_Time*)o)->data[1])
#define PyDateTime_TIME_GET_SECOND(o) (((PyDateTime_Time*)o)->data[2]) #define PyDateTime_TIME_GET_SECOND(o) (((PyDateTime_Time*)o)->data[2])
...@@ -113,9 +121,6 @@ typedef struct ...@@ -113,9 +121,6 @@ typedef struct
#define PyTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeType) #define PyTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeType)
#define PyTime_CheckExact(op) ((op)->ob_type == &PyDateTime_TimeType) #define PyTime_CheckExact(op) ((op)->ob_type == &PyDateTime_TimeType)
#define PyTimeTZ_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeTZType)
#define PyTimeTZ_CheckExact(op) ((op)->ob_type == &PyDateTime_TimeTZType)
#define PyDelta_Check(op) PyObject_TypeCheck(op, &PyDateTime_DeltaType) #define PyDelta_Check(op) PyObject_TypeCheck(op, &PyDateTime_DeltaType)
#define PyDelta_CheckExact(op) ((op)->ob_type == &PyDateTime_DeltaType) #define PyDelta_CheckExact(op) ((op)->ob_type == &PyDateTime_DeltaType)
......
...@@ -1857,7 +1857,7 @@ class TestTimeTZ(TestTime, TZInfoBase): ...@@ -1857,7 +1857,7 @@ class TestTimeTZ(TestTime, TZInfoBase):
tinfo = PicklableFixedOffset(-300, 'cookie') tinfo = PicklableFixedOffset(-300, 'cookie')
orig = self.theclass(5, 6, 7, tzinfo=tinfo) orig = self.theclass(5, 6, 7, tzinfo=tinfo)
state = orig.__getstate__() state = orig.__getstate__()
derived = self.theclass() derived = self.theclass(tzinfo=FixedOffset(0, "UTC", 0))
derived.__setstate__(state) derived.__setstate__(state)
self.assertEqual(orig, derived) self.assertEqual(orig, derived)
self.failUnless(isinstance(derived.tzinfo, PicklableFixedOffset)) self.failUnless(isinstance(derived.tzinfo, PicklableFixedOffset))
......
...@@ -82,7 +82,6 @@ static PyTypeObject PyDateTime_DateTimeTZType; ...@@ -82,7 +82,6 @@ static PyTypeObject PyDateTime_DateTimeTZType;
static PyTypeObject PyDateTime_DeltaType; static PyTypeObject PyDateTime_DeltaType;
static PyTypeObject PyDateTime_TimeType; static PyTypeObject PyDateTime_TimeType;
static PyTypeObject PyDateTime_TZInfoType; static PyTypeObject PyDateTime_TZInfoType;
static PyTypeObject PyDateTime_TimeTZType;
/* --------------------------------------------------------------------------- /* ---------------------------------------------------------------------------
* Math utilities. * Math utilities.
...@@ -607,8 +606,8 @@ get_tzinfo_member(PyObject *self) ...@@ -607,8 +606,8 @@ get_tzinfo_member(PyObject *self)
if (PyDateTimeTZ_Check(self)) if (PyDateTimeTZ_Check(self))
tzinfo = ((PyDateTime_DateTimeTZ *)self)->tzinfo; tzinfo = ((PyDateTime_DateTimeTZ *)self)->tzinfo;
else if (PyTimeTZ_Check(self)) else if (PyTime_Check(self) && ((PyDateTime_Time *)self)->hastzinfo)
tzinfo = ((PyDateTime_TimeTZ *)self)->tzinfo; tzinfo = ((PyDateTime_Time *)self)->tzinfo;
return tzinfo; return tzinfo;
} }
...@@ -783,8 +782,8 @@ typedef enum { ...@@ -783,8 +782,8 @@ typedef enum {
/* an exception has been set; the caller should pass it on */ /* an exception has been set; the caller should pass it on */
OFFSET_ERROR, OFFSET_ERROR,
/* type isn't date, datetime, datetimetz subclass, time, or /* type isn't date, datetime, datetimetz subclass, or time
* timetz subclass * subclass
*/ */
OFFSET_UNKNOWN, OFFSET_UNKNOWN,
...@@ -792,13 +791,13 @@ typedef enum { ...@@ -792,13 +791,13 @@ typedef enum {
* datetime, * datetime,
* datetimetz with None tzinfo, * datetimetz with None tzinfo,
* datetimetz where utcoffset() returns None * datetimetz where utcoffset() returns None
* time, * time with !hastzinfo
* timetz with None tzinfo, * time with None tzinfo,
* timetz where utcoffset() returns None * time where utcoffset() returns None
*/ */
OFFSET_NAIVE, OFFSET_NAIVE,
/* timetz where utcoffset() doesn't return None, /* time where utcoffset() doesn't return None,
* datetimetz where utcoffset() doesn't return None * datetimetz where utcoffset() doesn't return None
*/ */
OFFSET_AWARE, OFFSET_AWARE,
...@@ -1264,7 +1263,7 @@ set_datetime_time_fields(PyDateTime_Date *self, int h, int m, int s, int us) ...@@ -1264,7 +1263,7 @@ set_datetime_time_fields(PyDateTime_Date *self, int h, int m, int s, int us)
DATE_SET_MICROSECOND(self, us); DATE_SET_MICROSECOND(self, us);
} }
/* For time and timetz. */ /* For time. */
static void static void
set_time_fields(PyDateTime_Time *self, int h, int m, int s, int us) set_time_fields(PyDateTime_Time *self, int h, int m, int s, int us)
{ {
...@@ -1327,30 +1326,23 @@ new_datetimetz(int year, int month, int day, int hour, int minute, ...@@ -1327,30 +1326,23 @@ new_datetimetz(int year, int month, int day, int hour, int minute,
/* Create a time instance with no range checking. */ /* Create a time instance with no range checking. */
static PyObject * static PyObject *
new_time(int hour, int minute, int second, int usecond) new_time(int hour, int minute, int second, int usecond, PyObject *tzinfo)
{ {
PyDateTime_Time *self; PyDateTime_Time *self;
char aware = tzinfo != Py_None;
self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
if (self != NULL) self = (PyDateTime_Time *)PyObject_MALLOC(aware ?
set_time_fields(self, hour, minute, second, usecond); sizeof(PyDateTime_Time) :
return (PyObject *) self; sizeof(_PyDateTime_BaseTime));
} if (self == NULL)
return PyErr_NoMemory();
/* Create a timetz instance with no range checking. */ self->hastzinfo = aware;
static PyObject * set_time_fields(self, hour, minute, second, usecond);
new_timetz(int hour, int minute, int second, int usecond, PyObject *tzinfo) if (aware) {
{
PyDateTime_TimeTZ *self;
self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
if (self != NULL) {
set_time_fields((PyDateTime_Time *)self,
hour, minute, second, usecond);
Py_INCREF(tzinfo); Py_INCREF(tzinfo);
self->tzinfo = tzinfo; self->tzinfo = tzinfo;
} }
return (PyObject *) self; return (PyObject *)PyObject_INIT(self, &PyDateTime_TimeType);
} }
/* Create a timedelta instance. Normalize the members iff normalize is /* Create a timedelta instance. Normalize the members iff normalize is
...@@ -1401,7 +1393,7 @@ static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */ ...@@ -1401,7 +1393,7 @@ static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */
static PyObject *date_unpickler_object = NULL; static PyObject *date_unpickler_object = NULL;
static PyObject *datetimetz_unpickler_object = NULL; static PyObject *datetimetz_unpickler_object = NULL;
static PyObject *tzinfo_unpickler_object = NULL; static PyObject *tzinfo_unpickler_object = NULL;
static PyObject *timetz_unpickler_object = NULL; static PyObject *time_unpickler_object = NULL;
/* --------------------------------------------------------------------------- /* ---------------------------------------------------------------------------
* Class implementations. * Class implementations.
...@@ -2953,7 +2945,7 @@ datetime_utcnow(PyObject *cls, PyObject *dummy) ...@@ -2953,7 +2945,7 @@ datetime_utcnow(PyObject *cls, PyObject *dummy)
} }
/* Return new datetime or datetimetz from date/datetime/datetimetz and /* Return new datetime or datetimetz from date/datetime/datetimetz and
* time/timetz arguments. * time arguments.
*/ */
static PyObject * static PyObject *
datetime_combine(PyObject *cls, PyObject *args, PyObject *kw) datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
...@@ -2974,9 +2966,11 @@ datetime_combine(PyObject *cls, PyObject *args, PyObject *kw) ...@@ -2974,9 +2966,11 @@ datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
TIME_GET_MINUTE(time), TIME_GET_MINUTE(time),
TIME_GET_SECOND(time), TIME_GET_SECOND(time),
TIME_GET_MICROSECOND(time)); TIME_GET_MICROSECOND(time));
if (result && PyTimeTZ_Check(time) && PyDateTimeTZ_Check(result)) { if (result &&
((PyDateTime_Time *)time)->hastzinfo &&
PyDateTimeTZ_Check(result)) {
/* Copy the tzinfo field. */ /* Copy the tzinfo field. */
replace_tzinfo(result, ((PyDateTime_TimeTZ *)time)->tzinfo); replace_tzinfo(result, ((PyDateTime_Time *)time)->tzinfo);
} }
return result; return result;
} }
...@@ -3343,11 +3337,11 @@ datetime_getdate(PyDateTime_DateTime *self) ...@@ -3343,11 +3337,11 @@ datetime_getdate(PyDateTime_DateTime *self)
static PyObject * static PyObject *
datetime_gettime(PyDateTime_DateTime *self) datetime_gettime(PyDateTime_DateTime *self)
{ {
return new_timetz(DATE_GET_HOUR(self), return new_time(DATE_GET_HOUR(self),
DATE_GET_MINUTE(self), DATE_GET_MINUTE(self),
DATE_GET_SECOND(self), DATE_GET_SECOND(self),
DATE_GET_MICROSECOND(self), DATE_GET_MICROSECOND(self),
Py_None); Py_None);
} }
static PyMethodDef datetime_methods[] = { static PyMethodDef datetime_methods[] = {
...@@ -3398,7 +3392,7 @@ static PyMethodDef datetime_methods[] = { ...@@ -3398,7 +3392,7 @@ static PyMethodDef datetime_methods[] = {
PyDoc_STR("Return datetime with new specified fields.")}, PyDoc_STR("Return datetime with new specified fields.")},
{"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS, {"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
PyDoc_STR("tz -> datetimetz with same date & time, and tzinfo=tz\n")}, PyDoc_STR("tz -> datetime with same date & time, and tzinfo=tz\n")},
{NULL, NULL} {NULL, NULL}
}; };
...@@ -3464,11 +3458,137 @@ statichere PyTypeObject PyDateTime_DateTimeType = { ...@@ -3464,11 +3458,137 @@ statichere PyTypeObject PyDateTime_DateTimeType = {
_PyObject_Del, /* tp_free */ _PyObject_Del, /* tp_free */
}; };
/*
* PyDateTime_TZInfo implementation.
*/
/* This is a pure abstract base class, so doesn't do anything beyond
* raising NotImplemented exceptions. Real tzinfo classes need
* to derive from this. This is mostly for clarity, and for efficiency in
* datetimetz and time constructors (their tzinfo arguments need to
* be subclasses of this tzinfo class, which is easy and quick to check).
*
* Note: For reasons having to do with pickling of subclasses, we have
* to allow tzinfo objects to be instantiated. This wasn't an issue
* in the Python implementation (__init__() could raise NotImplementedError
* there without ill effect), but doing so in the C implementation hit a
* brick wall.
*/
static PyObject *
tzinfo_nogo(const char* methodname)
{
PyErr_Format(PyExc_NotImplementedError,
"a tzinfo subclass must implement %s()",
methodname);
return NULL;
}
/* Methods. A subclass must implement these. */
static PyObject*
tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
{
return tzinfo_nogo("tzname");
}
static PyObject*
tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
{
return tzinfo_nogo("utcoffset");
}
static PyObject*
tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
{
return tzinfo_nogo("dst");
}
/*
* Pickle support. This is solely so that tzinfo subclasses can use
* pickling -- tzinfo itself is supposed to be uninstantiable. The
* pickler and unpickler functions are given module-level private
* names, and registered with copy_reg, by the module init function.
*/
static PyObject*
tzinfo_pickler(PyDateTime_TZInfo *self) {
return Py_BuildValue("O()", tzinfo_unpickler_object);
}
static PyObject*
tzinfo_unpickler(PyObject * unused) {
return PyType_GenericNew(&PyDateTime_TZInfoType, NULL, NULL);
}
static PyMethodDef tzinfo_methods[] = {
{"tzname", (PyCFunction)tzinfo_tzname, METH_O,
PyDoc_STR("datetime -> string name of time zone.")},
{"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
PyDoc_STR("datetime -> minutes east of UTC (negative for "
"west of UTC).")},
{"dst", (PyCFunction)tzinfo_dst, METH_O,
PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
{NULL, NULL}
};
static char tzinfo_doc[] =
PyDoc_STR("Abstract base class for time zone info objects.");
statichere PyTypeObject PyDateTime_TZInfoType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"datetime.tzinfo", /* tp_name */
sizeof(PyDateTime_TZInfo), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
Py_TPFLAGS_BASETYPE, /* tp_flags */
tzinfo_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
tzinfo_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, /* tp_free */
};
/* /*
* PyDateTime_Time implementation. * PyDateTime_Time implementation.
*/ */
/* Accessor properties. */ /* Accessor properties.
*/
static PyObject * static PyObject *
time_hour(PyDateTime_Time *self, void *unused) time_hour(PyDateTime_Time *self, void *unused)
...@@ -3482,6 +3602,7 @@ time_minute(PyDateTime_Time *self, void *unused) ...@@ -3482,6 +3602,7 @@ time_minute(PyDateTime_Time *self, void *unused)
return PyInt_FromLong(TIME_GET_MINUTE(self)); return PyInt_FromLong(TIME_GET_MINUTE(self));
} }
/* The name time_second conflicted with some platform header file. */
static PyObject * static PyObject *
py_time_second(PyDateTime_Time *self, void *unused) py_time_second(PyDateTime_Time *self, void *unused)
{ {
...@@ -3494,17 +3615,29 @@ time_microsecond(PyDateTime_Time *self, void *unused) ...@@ -3494,17 +3615,29 @@ time_microsecond(PyDateTime_Time *self, void *unused)
return PyInt_FromLong(TIME_GET_MICROSECOND(self)); return PyInt_FromLong(TIME_GET_MICROSECOND(self));
} }
static PyObject *
time_tzinfo(PyDateTime_Time *self, void *unused)
{
PyObject *result = self->hastzinfo ? self->tzinfo : Py_None;
Py_INCREF(result);
return result;
}
static PyGetSetDef time_getset[] = { static PyGetSetDef time_getset[] = {
{"hour", (getter)time_hour}, {"hour", (getter)time_hour},
{"minute", (getter)time_minute}, {"minute", (getter)time_minute},
{"second", (getter)py_time_second}, {"second", (getter)py_time_second},
{"microsecond", (getter)time_microsecond}, {"microsecond", (getter)time_microsecond},
{"tzinfo", (getter)time_tzinfo},
{NULL} {NULL}
}; };
/* Constructors. */ /*
* Constructors.
*/
static char *time_kws[] = {"hour", "minute", "second", "microsecond", NULL}; static char *time_kws[] = {"hour", "minute", "second", "microsecond",
"tzinfo", NULL};
static PyObject * static PyObject *
time_new(PyTypeObject *type, PyObject *args, PyObject *kw) time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
...@@ -3514,18 +3647,58 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw) ...@@ -3514,18 +3647,58 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
int minute = 0; int minute = 0;
int second = 0; int second = 0;
int usecond = 0; int usecond = 0;
PyObject *tzinfo = Py_None;
if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", time_kws,
if (PyArg_ParseTupleAndKeywords(args, kw, "|iiii", time_kws, &hour, &minute, &second, &usecond,
&hour, &minute, &second, &usecond)) { &tzinfo)) {
if (check_time_args(hour, minute, second, usecond) < 0) if (check_time_args(hour, minute, second, usecond) < 0)
return NULL; return NULL;
self = new_time(hour, minute, second, usecond); if (check_tzinfo_subclass(tzinfo) < 0)
return NULL;
self = new_time(hour, minute, second, usecond, tzinfo);
} }
return self; return self;
} }
/* Various ways to turn a time into a string. */ /*
* Destructor.
*/
static void
time_dealloc(PyDateTime_Time *self)
{
if (self->hastzinfo)
Py_XDECREF(self->tzinfo);
self->ob_type->tp_free((PyObject *)self);
}
/*
* Indirect access to tzinfo methods.
*/
/* These are all METH_NOARGS, so don't need to check the arglist. */
static PyObject *
time_utcoffset(PyDateTime_Time *self, PyObject *unused) {
return offset_as_timedelta(self->hastzinfo ? self->tzinfo : Py_None,
"utcoffset", Py_None);
}
static PyObject *
time_dst(PyDateTime_Time *self, PyObject *unused) {
return offset_as_timedelta(self->hastzinfo ? self->tzinfo : Py_None,
"dst", Py_None);
}
static PyObject *
time_tzname(PyDateTime_Time *self, PyObject *unused) {
return call_tzname(self->hastzinfo ? self->tzinfo : Py_None,
Py_None);
}
/*
* Various ways to turn a time into a string.
*/
static PyObject * static PyObject *
time_repr(PyDateTime_Time *self) time_repr(PyDateTime_Time *self)
...@@ -3536,6 +3709,7 @@ time_repr(PyDateTime_Time *self) ...@@ -3536,6 +3709,7 @@ time_repr(PyDateTime_Time *self)
int m = TIME_GET_MINUTE(self); int m = TIME_GET_MINUTE(self);
int s = TIME_GET_SECOND(self); int s = TIME_GET_SECOND(self);
int us = TIME_GET_MICROSECOND(self); int us = TIME_GET_MICROSECOND(self);
PyObject *result = NULL;
if (us) if (us)
PyOS_snprintf(buffer, sizeof(buffer), PyOS_snprintf(buffer, sizeof(buffer),
...@@ -3546,7 +3720,10 @@ time_repr(PyDateTime_Time *self) ...@@ -3546,7 +3720,10 @@ time_repr(PyDateTime_Time *self)
else else
PyOS_snprintf(buffer, sizeof(buffer), PyOS_snprintf(buffer, sizeof(buffer),
"%s(%d, %d)", typename, h, m); "%s(%d, %d)", typename, h, m);
return PyString_FromString(buffer); result = PyString_FromString(buffer);
if (result != NULL && self->hastzinfo)
result = append_keyword_tzinfo(result, self->tzinfo);
return result;
} }
static PyObject * static PyObject *
...@@ -3558,7 +3735,8 @@ time_str(PyDateTime_Time *self) ...@@ -3558,7 +3735,8 @@ time_str(PyDateTime_Time *self)
static PyObject * static PyObject *
time_isoformat(PyDateTime_Time *self) time_isoformat(PyDateTime_Time *self)
{ {
char buffer[100]; char buf[100];
PyObject *result;
/* Reuse the time format code from the datetime type. */ /* Reuse the time format code from the datetime type. */
PyDateTime_DateTime datetime; PyDateTime_DateTime datetime;
PyDateTime_DateTime *pdatetime = &datetime; PyDateTime_DateTime *pdatetime = &datetime;
...@@ -3568,8 +3746,19 @@ time_isoformat(PyDateTime_Time *self) ...@@ -3568,8 +3746,19 @@ time_isoformat(PyDateTime_Time *self)
self->data, self->data,
_PyDateTime_TIME_DATASIZE); _PyDateTime_TIME_DATASIZE);
isoformat_time(pdatetime, buffer, sizeof(buffer)); isoformat_time(pdatetime, buf, sizeof(buf));
return PyString_FromString(buffer); result = PyString_FromString(buf);
if (result == NULL || ! self->hastzinfo || self->tzinfo == Py_None)
return result;
/* We need to append the UTC offset. */
if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Py_None) < 0) {
Py_DECREF(result);
return NULL;
}
PyString_ConcatAndDel(&result, PyString_FromString(buf));
return result;
} }
static PyObject * static PyObject *
...@@ -3602,12 +3791,13 @@ time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw) ...@@ -3602,12 +3791,13 @@ time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
return result; return result;
} }
/* Miscellaneous methods. */ /*
* Miscellaneous methods.
*/
/* This is more natural as a tp_compare, but doesn't work then: for whatever /* This is more natural as a tp_compare, but doesn't work then: for whatever
* reason, Python's try_3way_compare ignores tp_compare unless * reason, Python's try_3way_compare ignores tp_compare unless
* PyInstance_Check returns true, but these aren't old-style classes. * PyInstance_Check returns true, but these aren't old-style classes.
* Note that this routine handles all comparisons for time and timetz.
*/ */
static PyObject * static PyObject *
time_richcompare(PyDateTime_Time *self, PyObject *other, int op) time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
...@@ -3685,7 +3875,7 @@ time_hash(PyDateTime_Time *self) ...@@ -3685,7 +3875,7 @@ time_hash(PyDateTime_Time *self)
int minute; int minute;
assert(n == OFFSET_AWARE); assert(n == OFFSET_AWARE);
assert(PyTimeTZ_Check(self)); assert(self->hastzinfo);
hour = divmod(TIME_GET_HOUR(self) * 60 + hour = divmod(TIME_GET_HOUR(self) * 60 +
TIME_GET_MINUTE(self) - offset, TIME_GET_MINUTE(self) - offset,
60, 60,
...@@ -3693,7 +3883,8 @@ time_hash(PyDateTime_Time *self) ...@@ -3693,7 +3883,8 @@ time_hash(PyDateTime_Time *self)
if (0 <= hour && hour < 24) if (0 <= hour && hour < 24)
temp = new_time(hour, minute, temp = new_time(hour, minute,
TIME_GET_SECOND(self), TIME_GET_SECOND(self),
TIME_GET_MICROSECOND(self)); TIME_GET_MICROSECOND(self),
Py_None);
else else
temp = Py_BuildValue("iiii", temp = Py_BuildValue("iiii",
hour, minute, hour, minute,
...@@ -3717,12 +3908,13 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw) ...@@ -3717,12 +3908,13 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
int mm = TIME_GET_MINUTE(self); int mm = TIME_GET_MINUTE(self);
int ss = TIME_GET_SECOND(self); int ss = TIME_GET_SECOND(self);
int us = TIME_GET_MICROSECOND(self); int us = TIME_GET_MICROSECOND(self);
PyObject *tzinfo = self->hastzinfo ? self->tzinfo : Py_None;
if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiii:replace", if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
time_kws, time_kws,
&hh, &mm, &ss, &us)) &hh, &mm, &ss, &us, &tzinfo))
return NULL; return NULL;
tuple = Py_BuildValue("iiii", hh, mm, ss, us); tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
if (tuple == NULL) if (tuple == NULL)
return NULL; return NULL;
clone = time_new(self->ob_type, tuple, NULL); clone = time_new(self->ob_type, tuple, NULL);
...@@ -3733,408 +3925,55 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw) ...@@ -3733,408 +3925,55 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
static int static int
time_nonzero(PyDateTime_Time *self) time_nonzero(PyDateTime_Time *self)
{ {
return TIME_GET_HOUR(self) || int offset;
TIME_GET_MINUTE(self) || int none;
TIME_GET_SECOND(self) ||
TIME_GET_MICROSECOND(self); if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
/* Since utcoffset is in whole minutes, nothing can
* alter the conclusion that this is nonzero.
*/
return 1;
}
offset = 0;
if (self->hastzinfo && self->tzinfo != Py_None) {
offset = call_utcoffset(self->tzinfo, Py_None, &none);
if (offset == -1 && PyErr_Occurred())
return -1;
}
return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
} }
static PyMethodDef time_methods[] = { /*
{"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS, * Pickle support. Quite a maze!
PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm].")}, */
{"strftime", (PyCFunction)time_strftime, METH_KEYWORDS, /* Let basestate be the non-tzinfo data string.
PyDoc_STR("format -> strftime() style string.")}, * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
* So it's a tuple in any (non-error) case.
*/
static PyObject *
time_getstate(PyDateTime_Time *self)
{
PyObject *basestate;
PyObject *result = NULL;
{"replace", (PyCFunction)time_replace, METH_KEYWORDS, basestate = PyString_FromStringAndSize((char *)self->data,
PyDoc_STR("Return datetime with new specified fields.")}, _PyDateTime_TIME_DATASIZE);
{NULL, NULL} if (basestate != NULL) {
}; if (! self->hastzinfo || self->tzinfo == Py_None)
result = Py_BuildValue("(O)", basestate);
else
result = Py_BuildValue("OO", basestate, self->tzinfo);
Py_DECREF(basestate);
}
return result;
}
static char time_doc[] = static PyObject *
PyDoc_STR("Basic time type."); time_setstate(PyDateTime_Time *self, PyObject *state)
{
static PyNumberMethods time_as_number = { PyObject *basestate;
0, /* nb_add */ PyObject *tzinfo = Py_None;
0, /* nb_subtract */
0, /* nb_multiply */
0, /* nb_divide */
0, /* nb_remainder */
0, /* nb_divmod */
0, /* nb_power */
0, /* nb_negative */
0, /* nb_positive */
0, /* nb_absolute */
(inquiry)time_nonzero, /* nb_nonzero */
};
statichere PyTypeObject PyDateTime_TimeType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"datetime.time", /* tp_name */
sizeof(PyDateTime_Time), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)PyObject_Del, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)time_repr, /* tp_repr */
&time_as_number, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)time_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)time_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
Py_TPFLAGS_BASETYPE, /* tp_flags */
time_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)time_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
time_methods, /* tp_methods */
0, /* tp_members */
time_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
time_new, /* tp_new */
_PyObject_Del, /* tp_free */
};
/*
* PyDateTime_TZInfo implementation.
*/
/* This is a pure abstract base class, so doesn't do anything beyond
* raising NotImplemented exceptions. Real tzinfo classes need
* to derive from this. This is mostly for clarity, and for efficiency in
* datetimetz and timetz constructors (their tzinfo arguments need to
* be subclasses of this tzinfo class, which is easy and quick to check).
*
* Note: For reasons having to do with pickling of subclasses, we have
* to allow tzinfo objects to be instantiated. This wasn't an issue
* in the Python implementation (__init__() could raise NotImplementedError
* there without ill effect), but doing so in the C implementation hit a
* brick wall.
*/
static PyObject *
tzinfo_nogo(const char* methodname)
{
PyErr_Format(PyExc_NotImplementedError,
"a tzinfo subclass must implement %s()",
methodname);
return NULL;
}
/* Methods. A subclass must implement these. */
static PyObject*
tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
{
return tzinfo_nogo("tzname");
}
static PyObject*
tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
{
return tzinfo_nogo("utcoffset");
}
static PyObject*
tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
{
return tzinfo_nogo("dst");
}
/*
* Pickle support. This is solely so that tzinfo subclasses can use
* pickling -- tzinfo itself is supposed to be uninstantiable. The
* pickler and unpickler functions are given module-level private
* names, and registered with copy_reg, by the module init function.
*/
static PyObject*
tzinfo_pickler(PyDateTime_TZInfo *self) {
return Py_BuildValue("O()", tzinfo_unpickler_object);
}
static PyObject*
tzinfo_unpickler(PyObject * unused) {
return PyType_GenericNew(&PyDateTime_TZInfoType, NULL, NULL);
}
static PyMethodDef tzinfo_methods[] = {
{"tzname", (PyCFunction)tzinfo_tzname, METH_O,
PyDoc_STR("datetime -> string name of time zone.")},
{"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
PyDoc_STR("datetime -> minutes east of UTC (negative for "
"west of UTC).")},
{"dst", (PyCFunction)tzinfo_dst, METH_O,
PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
{NULL, NULL}
};
static char tzinfo_doc[] =
PyDoc_STR("Abstract base class for time zone info objects.");
statichere PyTypeObject PyDateTime_TZInfoType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"datetime.tzinfo", /* tp_name */
sizeof(PyDateTime_TZInfo), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
Py_TPFLAGS_BASETYPE, /* tp_flags */
tzinfo_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
tzinfo_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, /* tp_free */
};
/*
* PyDateTime_TimeTZ implementation.
*/
/* Accessor properties. Properties for hour, minute, second and microsecond
* are inherited from time.
*/
static PyObject *
timetz_tzinfo(PyDateTime_TimeTZ *self, void *unused)
{
Py_INCREF(self->tzinfo);
return self->tzinfo;
}
static PyGetSetDef timetz_getset[] = {
{"tzinfo", (getter)timetz_tzinfo},
{NULL}
};
/*
* Constructors.
*/
static char *timetz_kws[] = {"hour", "minute", "second", "microsecond",
"tzinfo", NULL};
static PyObject *
timetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
PyObject *self = NULL;
int hour = 0;
int minute = 0;
int second = 0;
int usecond = 0;
PyObject *tzinfo = Py_None;
if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", timetz_kws,
&hour, &minute, &second, &usecond,
&tzinfo)) {
if (check_time_args(hour, minute, second, usecond) < 0)
return NULL;
if (check_tzinfo_subclass(tzinfo) < 0)
return NULL;
self = new_timetz(hour, minute, second, usecond, tzinfo);
}
return self;
}
/*
* Destructor.
*/
static void
timetz_dealloc(PyDateTime_TimeTZ *self)
{
Py_XDECREF(self->tzinfo);
self->ob_type->tp_free((PyObject *)self);
}
/*
* Indirect access to tzinfo methods.
*/
/* These are all METH_NOARGS, so don't need to check the arglist. */
static PyObject *
timetz_utcoffset(PyDateTime_TimeTZ *self, PyObject *unused) {
return offset_as_timedelta(self->tzinfo, "utcoffset", Py_None);
}
static PyObject *
timetz_dst(PyDateTime_TimeTZ *self, PyObject *unused) {
return offset_as_timedelta(self->tzinfo, "dst", Py_None);
}
static PyObject *
timetz_tzname(PyDateTime_TimeTZ *self, PyObject *unused) {
return call_tzname(self->tzinfo, Py_None);
}
/*
* Various ways to turn a timetz into a string.
*/
static PyObject *
timetz_repr(PyDateTime_TimeTZ *self)
{
PyObject *baserepr = time_repr((PyDateTime_Time *)self);
if (baserepr == NULL)
return NULL;
return append_keyword_tzinfo(baserepr, self->tzinfo);
}
/* Note: tp_str is inherited from time. */
static PyObject *
timetz_isoformat(PyDateTime_TimeTZ *self)
{
char buf[100];
PyObject *result = time_isoformat((PyDateTime_Time *)self);
if (result == NULL || self->tzinfo == Py_None)
return result;
/* We need to append the UTC offset. */
if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Py_None) < 0) {
Py_DECREF(result);
return NULL;
}
PyString_ConcatAndDel(&result, PyString_FromString(buf));
return result;
}
/* Note: strftime() is inherited from time. */
/*
* Miscellaneous methods.
*/
/* Note: tp_richcompare and tp_hash are inherited from time. */
static PyObject *
timetz_replace(PyDateTime_TimeTZ *self, PyObject *args, PyObject *kw)
{
PyObject *clone;
PyObject *tuple;
int hh = TIME_GET_HOUR(self);
int mm = TIME_GET_MINUTE(self);
int ss = TIME_GET_SECOND(self);
int us = TIME_GET_MICROSECOND(self);
PyObject *tzinfo = self->tzinfo;
if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
timetz_kws,
&hh, &mm, &ss, &us, &tzinfo))
return NULL;
tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
if (tuple == NULL)
return NULL;
clone = timetz_new(self->ob_type, tuple, NULL);
Py_DECREF(tuple);
return clone;
}
static int
timetz_nonzero(PyDateTime_TimeTZ *self)
{
int offset;
int none;
if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
/* Since utcoffset is in whole minutes, nothing can
* alter the conclusion that this is nonzero.
*/
return 1;
}
offset = 0;
if (self->tzinfo != Py_None) {
offset = call_utcoffset(self->tzinfo, Py_None, &none);
if (offset == -1 && PyErr_Occurred())
return -1;
}
return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
}
/*
* Pickle support. Quite a maze!
*/
/* Let basestate be the non-tzinfo data string.
* If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
* So it's a tuple in any (non-error) case.
*/
static PyObject *
timetz_getstate(PyDateTime_TimeTZ *self)
{
PyObject *basestate;
PyObject *result = NULL;
basestate = PyString_FromStringAndSize((char *)self->data,
_PyDateTime_TIME_DATASIZE);
if (basestate != NULL) {
if (self->tzinfo == Py_None)
result = Py_BuildValue("(O)", basestate);
else
result = Py_BuildValue("OO", basestate, self->tzinfo);
Py_DECREF(basestate);
}
return result;
}
static PyObject *
timetz_setstate(PyDateTime_TimeTZ *self, PyObject *state)
{
PyObject *basestate;
PyObject *tzinfo = Py_None;
if (! PyArg_ParseTuple(state, "O!|O:__setstate__", if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
&PyString_Type, &basestate, &PyString_Type, &basestate,
...@@ -4146,33 +3985,41 @@ timetz_setstate(PyDateTime_TimeTZ *self, PyObject *state) ...@@ -4146,33 +3985,41 @@ timetz_setstate(PyDateTime_TimeTZ *self, PyObject *state)
"bad argument to time.__setstate__"); "bad argument to time.__setstate__");
return NULL; return NULL;
} }
if (tzinfo != Py_None && ! self->hastzinfo) {
PyErr_SetString(PyExc_ValueError, "time.__setstate__ can't "
"add a non-None tzinfo to a time object that "
"doesn't have one already");
return NULL;
}
memcpy((char *)self->data, memcpy((char *)self->data,
PyString_AsString(basestate), PyString_AsString(basestate),
_PyDateTime_TIME_DATASIZE); _PyDateTime_TIME_DATASIZE);
self->hashcode = -1; self->hashcode = -1;
Py_INCREF(tzinfo); if (self->hastzinfo) {
Py_XDECREF(self->tzinfo); Py_INCREF(tzinfo);
self->tzinfo = tzinfo; Py_XDECREF(self->tzinfo);
self->tzinfo = tzinfo;
}
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
static PyObject * static PyObject *
timetz_pickler(PyObject *module, PyDateTime_TimeTZ *timetz) time_pickler(PyObject *module, PyDateTime_Time *time)
{ {
PyObject *state; PyObject *state;
PyObject *result = NULL; PyObject *result = NULL;
if (! PyTimeTZ_CheckExact(timetz)) { if (! PyTime_CheckExact(time)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"bad type passed to timetz pickler: %s", "bad type passed to time pickler: %s",
timetz->ob_type->tp_name); time->ob_type->tp_name);
return NULL; return NULL;
} }
state = timetz_getstate(timetz); state = time_getstate(time);
if (state) { if (state) {
result = Py_BuildValue("O(O)", result = Py_BuildValue("O(O)",
timetz_unpickler_object, time_unpickler_object,
state); state);
Py_DECREF(state); Py_DECREF(state);
} }
...@@ -4180,55 +4027,70 @@ timetz_pickler(PyObject *module, PyDateTime_TimeTZ *timetz) ...@@ -4180,55 +4027,70 @@ timetz_pickler(PyObject *module, PyDateTime_TimeTZ *timetz)
} }
static PyObject * static PyObject *
timetz_unpickler(PyObject *module, PyObject *arg) time_unpickler(PyObject *module, PyObject *arg)
{ {
PyDateTime_TimeTZ *self; PyDateTime_Time *self;
PyObject *tzinfo = Py_None;
self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType); /* We don't want to allocate space for tzinfo if it's not needed.
* Figuring that out in advance is irritating, so for now we
* realloc later.
*/
self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
if (self != NULL) { if (self != NULL) {
PyObject *res; PyObject *res;
self->tzinfo = NULL; self->tzinfo = Py_None;
res = timetz_setstate(self, arg); Py_INCREF(self->tzinfo);
self->hastzinfo = (char)1; /* true */
res = time_setstate(self, arg);
if (res == NULL) { if (res == NULL) {
Py_DECREF(self); Py_DECREF(self);
return NULL; return NULL;
} }
Py_DECREF(res); Py_DECREF(res);
if (self->tzinfo == Py_None) {
/* shrinking; can't fail */
Py_DECREF(self->tzinfo);
PyObject_Realloc(self, sizeof(_PyDateTime_BaseTime));
self->hastzinfo = (char)0;
}
} }
return (PyObject *)self; return (PyObject *)self;
} }
static PyMethodDef timetz_methods[] = { static PyMethodDef time_methods[] = {
{"isoformat", (PyCFunction)timetz_isoformat, METH_KEYWORDS, {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]" PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
"[+HH:MM].")}, "[+HH:MM].")},
{"utcoffset", (PyCFunction)timetz_utcoffset, METH_NOARGS, {"strftime", (PyCFunction)time_strftime, METH_KEYWORDS,
PyDoc_STR("format -> strftime() style string.")},
{"utcoffset", (PyCFunction)time_utcoffset, METH_NOARGS,
PyDoc_STR("Return self.tzinfo.utcoffset(self).")}, PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
{"tzname", (PyCFunction)timetz_tzname, METH_NOARGS, {"tzname", (PyCFunction)time_tzname, METH_NOARGS,
PyDoc_STR("Return self.tzinfo.tzname(self).")}, PyDoc_STR("Return self.tzinfo.tzname(self).")},
{"dst", (PyCFunction)timetz_dst, METH_NOARGS, {"dst", (PyCFunction)time_dst, METH_NOARGS,
PyDoc_STR("Return self.tzinfo.dst(self).")}, PyDoc_STR("Return self.tzinfo.dst(self).")},
{"replace", (PyCFunction)timetz_replace, METH_KEYWORDS, {"replace", (PyCFunction)time_replace, METH_KEYWORDS,
PyDoc_STR("Return timetz with new specified fields.")}, PyDoc_STR("Return time with new specified fields.")},
{"__setstate__", (PyCFunction)timetz_setstate, METH_O, {"__setstate__", (PyCFunction)time_setstate, METH_O,
PyDoc_STR("__setstate__(state)")}, PyDoc_STR("__setstate__(state)")},
{"__getstate__", (PyCFunction)timetz_getstate, METH_NOARGS, {"__getstate__", (PyCFunction)time_getstate, METH_NOARGS,
PyDoc_STR("__getstate__() -> state")}, PyDoc_STR("__getstate__() -> state")},
{NULL, NULL} {NULL, NULL}
}; };
static char timetz_doc[] = static char time_doc[] =
PyDoc_STR("Time type."); PyDoc_STR("Time type.");
static PyNumberMethods timetz_as_number = { static PyNumberMethods time_as_number = {
0, /* nb_add */ 0, /* nb_add */
0, /* nb_subtract */ 0, /* nb_subtract */
0, /* nb_multiply */ 0, /* nb_multiply */
...@@ -4239,50 +4101,50 @@ static PyNumberMethods timetz_as_number = { ...@@ -4239,50 +4101,50 @@ static PyNumberMethods timetz_as_number = {
0, /* nb_negative */ 0, /* nb_negative */
0, /* nb_positive */ 0, /* nb_positive */
0, /* nb_absolute */ 0, /* nb_absolute */
(inquiry)timetz_nonzero, /* nb_nonzero */ (inquiry)time_nonzero, /* nb_nonzero */
}; };
statichere PyTypeObject PyDateTime_TimeTZType = { statichere PyTypeObject PyDateTime_TimeType = {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /* ob_size */ 0, /* ob_size */
"datetime.time", /* tp_name */ "datetime.time", /* tp_name */
sizeof(PyDateTime_TimeTZ), /* tp_basicsize */ sizeof(PyDateTime_Time), /* tp_basicsize */
0, /* tp_itemsize */ 0, /* tp_itemsize */
(destructor)timetz_dealloc, /* tp_dealloc */ (destructor)time_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
0, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
(reprfunc)timetz_repr, /* tp_repr */ (reprfunc)time_repr, /* tp_repr */
&timetz_as_number, /* tp_as_number */ &time_as_number, /* tp_as_number */
0, /* tp_as_sequence */ 0, /* tp_as_sequence */
0, /* tp_as_mapping */ 0, /* tp_as_mapping */
0, /* tp_hash */ (hashfunc)time_hash, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ (reprfunc)time_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
Py_TPFLAGS_BASETYPE, /* tp_flags */ Py_TPFLAGS_BASETYPE, /* tp_flags */
timetz_doc, /* tp_doc */ time_doc, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ (richcmpfunc)time_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
0, /* tp_iter */ 0, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
timetz_methods, /* tp_methods */ time_methods, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
timetz_getset, /* tp_getset */ time_getset, /* tp_getset */
&PyDateTime_TimeType, /* tp_base */ 0, /* tp_base */
0, /* tp_dict */ 0, /* tp_dict */
0, /* tp_descr_get */ 0, /* tp_descr_get */
0, /* tp_descr_set */ 0, /* tp_descr_set */
0, /* tp_dictoffset */ 0, /* tp_dictoffset */
0, /* tp_init */ 0, /* tp_init */
0, /* tp_alloc */ 0, /* tp_alloc */
timetz_new, /* tp_new */ time_new, /* tp_new */
_PyObject_Del, /* tp_free */ _PyObject_Del, /* tp_free */
}; };
...@@ -4789,11 +4651,11 @@ datetimetz_utctimetuple(PyDateTime_DateTimeTZ *self) ...@@ -4789,11 +4651,11 @@ datetimetz_utctimetuple(PyDateTime_DateTimeTZ *self)
static PyObject * static PyObject *
datetimetz_gettimetz(PyDateTime_DateTimeTZ *self) datetimetz_gettimetz(PyDateTime_DateTimeTZ *self)
{ {
return new_timetz(DATE_GET_HOUR(self), return new_time(DATE_GET_HOUR(self),
DATE_GET_MINUTE(self), DATE_GET_MINUTE(self),
DATE_GET_SECOND(self), DATE_GET_SECOND(self),
DATE_GET_MICROSECOND(self), DATE_GET_MICROSECOND(self),
self->tzinfo); self->tzinfo);
} }
/* /*
...@@ -5019,8 +4881,8 @@ static PyMethodDef module_methods[] = { ...@@ -5019,8 +4881,8 @@ static PyMethodDef module_methods[] = {
{"_date_unpickler", (PyCFunction)date_unpickler, METH_O, NULL}, {"_date_unpickler", (PyCFunction)date_unpickler, METH_O, NULL},
{"_datetimetz_pickler", (PyCFunction)datetimetz_pickler,METH_O, NULL}, {"_datetimetz_pickler", (PyCFunction)datetimetz_pickler,METH_O, NULL},
{"_datetimetz_unpickler",(PyCFunction)datetimetz_unpickler,METH_O, NULL}, {"_datetimetz_unpickler",(PyCFunction)datetimetz_unpickler,METH_O, NULL},
{"_timetz_pickler", (PyCFunction)timetz_pickler, METH_O, NULL}, {"_time_pickler", (PyCFunction)time_pickler, METH_O, NULL},
{"_timetz_unpickler", (PyCFunction)timetz_unpickler, METH_O, NULL}, {"_time_unpickler", (PyCFunction)time_unpickler, METH_O, NULL},
{"_tzinfo_pickler", (PyCFunction)tzinfo_pickler, METH_O, NULL}, {"_tzinfo_pickler", (PyCFunction)tzinfo_pickler, METH_O, NULL},
{"_tzinfo_unpickler", (PyCFunction)tzinfo_unpickler, METH_NOARGS, {"_tzinfo_unpickler", (PyCFunction)tzinfo_unpickler, METH_NOARGS,
NULL}, NULL},
...@@ -5054,8 +4916,6 @@ initdatetime(void) ...@@ -5054,8 +4916,6 @@ initdatetime(void)
return; return;
if (PyType_Ready(&PyDateTime_TZInfoType) < 0) if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
return; return;
if (PyType_Ready(&PyDateTime_TimeTZType) < 0)
return;
if (PyType_Ready(&PyDateTime_DateTimeTZType) < 0) if (PyType_Ready(&PyDateTime_DateTimeTZType) < 0)
return; return;
...@@ -5079,15 +4939,15 @@ initdatetime(void) ...@@ -5079,15 +4939,15 @@ initdatetime(void)
Py_DECREF(x); Py_DECREF(x);
Py_DECREF(pickler); Py_DECREF(pickler);
pickler = PyObject_GetAttrString(m, "_timetz_pickler"); pickler = PyObject_GetAttrString(m, "_time_pickler");
if (pickler == NULL) return; if (pickler == NULL) return;
timetz_unpickler_object = PyObject_GetAttrString(m, time_unpickler_object = PyObject_GetAttrString(m,
"_timetz_unpickler"); "_time_unpickler");
if (timetz_unpickler_object == NULL) return; if (time_unpickler_object == NULL) return;
x = PyObject_CallMethod(copyreg, "pickle", "OOO", x = PyObject_CallMethod(copyreg, "pickle", "OOO",
&PyDateTime_TimeTZType, &PyDateTime_TimeType,
pickler, pickler,
timetz_unpickler_object); time_unpickler_object);
if (x == NULL) return; if (x == NULL) return;
Py_DECREF(x); Py_DECREF(x);
Py_DECREF(pickler); Py_DECREF(pickler);
...@@ -5160,15 +5020,15 @@ initdatetime(void) ...@@ -5160,15 +5020,15 @@ initdatetime(void)
return; return;
Py_DECREF(x); Py_DECREF(x);
/* timetz values */ /* time values */
d = PyDateTime_TimeTZType.tp_dict; d = PyDateTime_TimeType.tp_dict;
x = new_timetz(0, 0, 0, 0, Py_None); x = new_time(0, 0, 0, 0, Py_None);
if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
return; return;
Py_DECREF(x); Py_DECREF(x);
x = new_timetz(23, 59, 59, 999999, Py_None); x = new_time(23, 59, 59, 999999, Py_None);
if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
return; return;
Py_DECREF(x); Py_DECREF(x);
...@@ -5211,8 +5071,8 @@ initdatetime(void) ...@@ -5211,8 +5071,8 @@ initdatetime(void)
Py_INCREF(&PyDateTime_TZInfoType); Py_INCREF(&PyDateTime_TZInfoType);
PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType); PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
Py_INCREF(&PyDateTime_TimeTZType); Py_INCREF(&PyDateTime_TimeType);
PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeTZType); PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
Py_INCREF(&PyDateTime_DateTimeTZType); Py_INCREF(&PyDateTime_DateTimeTZType);
PyModule_AddObject(m, "datetime", PyModule_AddObject(m, "datetime",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment