/* # of bytes for year, month, day, hour, minute, second, and usecond. */
#define _PyDateTime_DATETIME_DATASIZE 10
-#define _PyTZINFO_HEAD \
- PyObject_HEAD \
- long hashcode; \
- char hastzinfo; /* boolean flag */
typedef struct
{
PyObject_HEAD
- long hashcode;
- unsigned char data[_PyDateTime_DATE_DATASIZE];
-} PyDateTime_Date;
+ long hashcode; /* -1 when unknown */
+ int days; /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
+ int seconds; /* 0 <= seconds < 24*3600 is invariant */
+ int microseconds; /* 0 <= microseconds < 1000000 is invariant */
+} PyDateTime_Delta;
typedef struct
{
- PyObject_HEAD
- long hashcode;
- unsigned char data[_PyDateTime_DATETIME_DATASIZE];
-} PyDateTime_DateTime;
+ PyObject_HEAD /* a pure abstract base clase */
+} PyDateTime_TZInfo;
typedef struct
{
PyObject_HEAD
long hashcode;
- unsigned char data[_PyDateTime_DATETIME_DATASIZE];
- PyObject *tzinfo;
-} PyDateTime_DateTimeTZ;
+ unsigned char data[_PyDateTime_DATE_DATASIZE];
+} PyDateTime_Date;
+/* The datetime and time types have hashcodes, and an optional tzinfo member,
+ * present if and only if hastzinfo is true.
+ */
+#define _PyTZINFO_HEAD \
+ PyObject_HEAD \
+ long hashcode; \
+ char hastzinfo; /* boolean flag */
+/* No _PyDateTime_BaseTZInfo is allocated; it's just to have something
+ * convenient to cast to, when getting at the hastzinfo member of objects
+ * starting with _PyTZINFO_HEAD.
+ */
+typedef struct
+{
+ _PyTZINFO_HEAD
+} _PyDateTime_BaseTZInfo;
+
+/* All time objects are of PyDateTime_TimeType, but that can be allocated
+ * in two ways, with or without a tzinfo member. Without is the same as
+ * tzinfo == None, but consumes less memory. _PyDateTime_BaseTime is an
+ * internal struct used to allocate the right amount of space for the
+ * "without" case.
+ */
#define _PyDateTime_TIMEHEAD \
_PyTZINFO_HEAD \
unsigned char data[_PyDateTime_TIME_DATASIZE];
PyObject *tzinfo;
} PyDateTime_Time; /* hastzinfo true */
+/* XXX The date type will be reworked similarly. */
typedef struct
{
PyObject_HEAD
- long hashcode; /* -1 when unknown */
- int days; /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
- int seconds; /* 0 <= seconds < 24*3600 is invariant */
- int microseconds; /* 0 <= microseconds < 1000000 is invariant */
-} PyDateTime_Delta;
+ long hashcode;
+ unsigned char data[_PyDateTime_DATETIME_DATASIZE];
+} PyDateTime_DateTime;
typedef struct
{
- PyObject_HEAD /* a pure abstract base clase */
-} PyDateTime_TZInfo;
+ PyObject_HEAD
+ long hashcode;
+ unsigned char data[_PyDateTime_DATETIME_DATASIZE];
+ PyObject *tzinfo;
+} PyDateTime_DateTimeTZ;
+
/* Apply for date, datetime, and datetimetz instances. */
#define PyDateTime_GET_YEAR(o) ((((PyDateTime_Date*)o)->data[0] << 8) | \
#define SET_TD_SECONDS(o, v) ((o)->seconds = (v))
#define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v))
+/* p is a pointer to a time or a datetime object; HASTZINFO(p) returns
+ * p->hastzinfo.
+ */
+#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo)
+
/* Forward declarations. */
static PyTypeObject PyDateTime_DateType;
static PyTypeObject PyDateTime_DateTimeType;
if (PyDateTimeTZ_Check(self))
tzinfo = ((PyDateTime_DateTimeTZ *)self)->tzinfo;
- else if (PyTime_Check(self) && ((PyDateTime_Time *)self)->hastzinfo)
+ else if (PyTime_Check(self) && HASTZINFO(self))
tzinfo = ((PyDateTime_Time *)self)->tzinfo;
return tzinfo;
TIME_GET_MINUTE(time),
TIME_GET_SECOND(time),
TIME_GET_MICROSECOND(time));
- if (result &&
- ((PyDateTime_Time *)time)->hastzinfo &&
- PyDateTimeTZ_Check(result)) {
+ if (result && HASTZINFO(time) && PyDateTimeTZ_Check(result)) {
/* Copy the tzinfo field. */
replace_tzinfo(result, ((PyDateTime_Time *)time)->tzinfo);
}
static PyObject *
time_tzinfo(PyDateTime_Time *self, void *unused)
{
- PyObject *result = self->hastzinfo ? self->tzinfo : Py_None;
+ PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
Py_INCREF(result);
return result;
}
static void
time_dealloc(PyDateTime_Time *self)
{
- if (self->hastzinfo) {
+ if (HASTZINFO(self)) {
Py_XDECREF(self->tzinfo);
}
self->ob_type->tp_free((PyObject *)self);
/* 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,
+ return offset_as_timedelta(HASTZINFO(self) ? 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,
+ return offset_as_timedelta(HASTZINFO(self) ? 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,
+ return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None,
Py_None);
}
PyOS_snprintf(buffer, sizeof(buffer),
"%s(%d, %d)", typename, h, m);
result = PyString_FromString(buffer);
- if (result != NULL && self->hastzinfo)
+ if (result != NULL && HASTZINFO(self))
result = append_keyword_tzinfo(result, self->tzinfo);
return result;
}
isoformat_time(pdatetime, buf, sizeof(buf));
result = PyString_FromString(buf);
- if (result == NULL || ! self->hastzinfo || self->tzinfo == Py_None)
+ if (result == NULL || ! HASTZINFO(self) || self->tzinfo == Py_None)
return result;
/* We need to append the UTC offset. */
int minute;
assert(n == OFFSET_AWARE);
- assert(self->hastzinfo);
+ assert(HASTZINFO(self));
hour = divmod(TIME_GET_HOUR(self) * 60 +
TIME_GET_MINUTE(self) - offset,
60,
int mm = TIME_GET_MINUTE(self);
int ss = TIME_GET_SECOND(self);
int us = TIME_GET_MICROSECOND(self);
- PyObject *tzinfo = self->hastzinfo ? self->tzinfo : Py_None;
+ PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
time_kws,
return 1;
}
offset = 0;
- if (self->hastzinfo && self->tzinfo != Py_None) {
+ if (HASTZINFO(self) && self->tzinfo != Py_None) {
offset = call_utcoffset(self->tzinfo, Py_None, &none);
if (offset == -1 && PyErr_Occurred())
return -1;
basestate = PyString_FromStringAndSize((char *)self->data,
_PyDateTime_TIME_DATASIZE);
if (basestate != NULL) {
- if (! self->hastzinfo || self->tzinfo == Py_None)
+ if (! HASTZINFO(self) || self->tzinfo == Py_None)
result = Py_BuildValue("(O)", basestate);
else
result = Py_BuildValue("OO", basestate, self->tzinfo);
"bad argument to time.__setstate__");
return NULL;
}
- if (tzinfo != Py_None && ! self->hastzinfo) {
+ if (tzinfo != Py_None && ! HASTZINFO(self)) {
PyErr_SetString(PyExc_ValueError, "time.__setstate__ can't "
"add a non-None tzinfo to a time object that "
"doesn't have one already");
PyString_AsString(basestate),
_PyDateTime_TIME_DATASIZE);
self->hashcode = -1;
- if (self->hastzinfo) {
+ if (HASTZINFO(self)) {
Py_INCREF(tzinfo);
Py_XDECREF(self->tzinfo);
self->tzinfo = tzinfo;