Got rid of the timetz type entirely. This was a bit trickier than I
authorTim Peters <tim.peters@gmail.com>
Fri, 10 Jan 2003 03:49:02 +0000 (03:49 +0000)
committerTim Peters <tim.peters@gmail.com>
Fri, 10 Jan 2003 03:49:02 +0000 (03:49 +0000)
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.

Include/datetime.h
Lib/test/test_datetime.py
Modules/datetimemodule.c

index 7bfbf0b3f3cf0a5500da2d652df240912809d03d..5c311620b929c33b700ac6bd0bea615078351658 100644 (file)
 /* # 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
@@ -49,20 +54,23 @@ typedef struct
        PyObject *tzinfo;
 } PyDateTime_DateTimeTZ;
 
+
+
+#define _PyDateTime_TIMEHEAD   \
+       _PyTZINFO_HEAD          \
+       unsigned char data[_PyDateTime_TIME_DATASIZE];
+
 typedef struct
 {
-       PyObject_HEAD
-       long hashcode;
-       unsigned char data[_PyDateTime_TIME_DATASIZE];
-} PyDateTime_Time;
+       _PyDateTime_TIMEHEAD
+} _PyDateTime_BaseTime;                /* hastzinfo false */
 
 typedef struct
 {
-       PyObject_HEAD
-       long hashcode;
-       unsigned char data[_PyDateTime_TIME_DATASIZE];
+       _PyDateTime_TIMEHEAD
        PyObject *tzinfo;
-} PyDateTime_TimeTZ;
+} PyDateTime_Time;             /* hastzinfo true */
+
 
 typedef struct
 {
@@ -92,7 +100,7 @@ typedef struct
          (((PyDateTime_DateTime*)o)->data[8] << 8)  |  \
           ((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_MINUTE(o)      (((PyDateTime_Time*)o)->data[1])
 #define PyDateTime_TIME_GET_SECOND(o)      (((PyDateTime_Time*)o)->data[2])
@@ -113,9 +121,6 @@ typedef struct
 #define PyTime_Check(op) PyObject_TypeCheck(op, &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_CheckExact(op) ((op)->ob_type == &PyDateTime_DeltaType)
 
index 614fed6d032576a1036081027bd3a016595e5788..0cda5d0c2d79368f0e927d158ed1fae6ade411d6 100644 (file)
@@ -1857,7 +1857,7 @@ class TestTimeTZ(TestTime, TZInfoBase):
         tinfo = PicklableFixedOffset(-300, 'cookie')
         orig = self.theclass(5, 6, 7, tzinfo=tinfo)
         state = orig.__getstate__()
-        derived = self.theclass()
+        derived = self.theclass(tzinfo=FixedOffset(0, "UTC", 0))
         derived.__setstate__(state)
         self.assertEqual(orig, derived)
         self.failUnless(isinstance(derived.tzinfo, PicklableFixedOffset))
index 642c11f9ed8b56e035fd9bc9be9bf02831e92f83..5840fb84cf0ca340cd4fb99651b33f52fa4815f7 100644 (file)
@@ -82,7 +82,6 @@ static PyTypeObject PyDateTime_DateTimeTZType;
 static PyTypeObject PyDateTime_DeltaType;
 static PyTypeObject PyDateTime_TimeType;
 static PyTypeObject PyDateTime_TZInfoType;
-static PyTypeObject PyDateTime_TimeTZType;
 
 /* ---------------------------------------------------------------------------
  * Math utilities.
@@ -607,8 +606,8 @@ get_tzinfo_member(PyObject *self)
 
        if (PyDateTimeTZ_Check(self))
                tzinfo = ((PyDateTime_DateTimeTZ *)self)->tzinfo;
-       else if (PyTimeTZ_Check(self))
-               tzinfo = ((PyDateTime_TimeTZ *)self)->tzinfo;
+       else if (PyTime_Check(self) && ((PyDateTime_Time *)self)->hastzinfo)
+               tzinfo = ((PyDateTime_Time *)self)->tzinfo;
 
        return tzinfo;
 }
@@ -783,8 +782,8 @@ typedef enum {
              /* an exception has been set; the caller should pass it on */
              OFFSET_ERROR,
 
-             /* type isn't date, datetime, datetimetz subclass, time, or
-              * timetz subclass
+             /* type isn't date, datetime, datetimetz subclass, or time
+              * subclass
               */
              OFFSET_UNKNOWN,
 
@@ -792,13 +791,13 @@ typedef enum {
               * datetime,
               * datetimetz with None tzinfo,
               * datetimetz where utcoffset() returns None
-              * time,
-              * timetz with None tzinfo,
-              * timetz where utcoffset() returns None
+              * time with !hastzinfo
+              * time with None tzinfo,
+              * time where utcoffset() returns None
               */
              OFFSET_NAIVE,
 
-             /* timetz where utcoffset() doesn't return None,
+             /* time where utcoffset() doesn't return None,
               * datetimetz where utcoffset() doesn't return None
               */
              OFFSET_AWARE,
@@ -1264,7 +1263,7 @@ set_datetime_time_fields(PyDateTime_Date *self, int h, int m, int s, int us)
        DATE_SET_MICROSECOND(self, us);
 }
 
-/* For time and timetz. */
+/* For time. */
 static void
 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,
 
 /* Create a time instance with no range checking. */
 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;
-
-       self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
-       if (self != NULL)
-               set_time_fields(self, hour, minute, second, usecond);
-       return (PyObject *) self;
-}
-
-/* Create a timetz instance with no range checking. */
-static PyObject *
-new_timetz(int hour, int minute, int second, int usecond, PyObject *tzinfo)
-{
-       PyDateTime_TimeTZ *self;
-
-       self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
-       if (self != NULL) {
-               set_time_fields((PyDateTime_Time *)self,
-                               hour, minute, second, usecond);
+       char aware = tzinfo != Py_None;
+
+       self = (PyDateTime_Time *)PyObject_MALLOC(aware ?
+                               sizeof(PyDateTime_Time) :
+                               sizeof(_PyDateTime_BaseTime));
+       if (self == NULL)
+               return PyErr_NoMemory();
+       self->hastzinfo = aware;
+       set_time_fields(self, hour, minute, second, usecond);
+       if (aware) {
                Py_INCREF(tzinfo);
                self->tzinfo = tzinfo;
        }
-       return (PyObject *) self;
+       return (PyObject *)PyObject_INIT(self, &PyDateTime_TimeType);
 }
 
 /* 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 */
 static PyObject *date_unpickler_object = NULL;
 static PyObject *datetimetz_unpickler_object = NULL;
 static PyObject *tzinfo_unpickler_object = NULL;
-static PyObject *timetz_unpickler_object = NULL;
+static PyObject *time_unpickler_object = NULL;
 
 /* ---------------------------------------------------------------------------
  * Class implementations.
@@ -2953,7 +2945,7 @@ datetime_utcnow(PyObject *cls, PyObject *dummy)
 }
 
 /* Return new datetime or datetimetz from date/datetime/datetimetz and
- * time/timetz arguments.
+ * time arguments.
  */
 static PyObject *
 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_SECOND(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. */
-               replace_tzinfo(result, ((PyDateTime_TimeTZ *)time)->tzinfo);
+               replace_tzinfo(result, ((PyDateTime_Time *)time)->tzinfo);
        }
        return result;
 }
@@ -3343,11 +3337,11 @@ datetime_getdate(PyDateTime_DateTime *self)
 static PyObject *
 datetime_gettime(PyDateTime_DateTime *self)
 {
-       return new_timetz(DATE_GET_HOUR(self),
-                         DATE_GET_MINUTE(self),
-                         DATE_GET_SECOND(self),
-                         DATE_GET_MICROSECOND(self),
-                         Py_None);
+       return new_time(DATE_GET_HOUR(self),
+                       DATE_GET_MINUTE(self),
+                       DATE_GET_SECOND(self),
+                       DATE_GET_MICROSECOND(self),
+                       Py_None);
 }
 
 static PyMethodDef datetime_methods[] = {
@@ -3398,7 +3392,7 @@ static PyMethodDef datetime_methods[] = {
         PyDoc_STR("Return datetime with new specified fields.")},
 
        {"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}
 };
@@ -3464,11 +3458,137 @@ statichere PyTypeObject PyDateTime_DateTimeType = {
        _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.
  */
 
-/* Accessor properties. */
+/* Accessor properties.
+ */
 
 static PyObject *
 time_hour(PyDateTime_Time *self, void *unused)
@@ -3482,6 +3602,7 @@ time_minute(PyDateTime_Time *self, void *unused)
        return PyInt_FromLong(TIME_GET_MINUTE(self));
 }
 
+/* The name time_second conflicted with some platform header file. */
 static PyObject *
 py_time_second(PyDateTime_Time *self, void *unused)
 {
@@ -3494,17 +3615,29 @@ time_microsecond(PyDateTime_Time *self, void *unused)
        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[] = {
        {"hour",        (getter)time_hour},
        {"minute",      (getter)time_minute},
        {"second",      (getter)py_time_second},
        {"microsecond", (getter)time_microsecond},
+       {"tzinfo",      (getter)time_tzinfo},
        {NULL}
 };
 
-/* Constructors. */
+/*
+ * Constructors.
+ */
 
-static char *time_kws[] = {"hour", "minute", "second", "microsecond", NULL};
+static char *time_kws[] = {"hour", "minute", "second", "microsecond",
+                          "tzinfo", NULL};
 
 static PyObject *
 time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
@@ -3514,18 +3647,58 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
        int minute = 0;
        int second = 0;
        int usecond = 0;
+       PyObject *tzinfo = Py_None;
 
-
-       if (PyArg_ParseTupleAndKeywords(args, kw, "|iiii", time_kws,
-                                       &hour, &minute, &second, &usecond)) {
+       if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", time_kws,
+                                       &hour, &minute, &second, &usecond,
+                                       &tzinfo)) {
                if (check_time_args(hour, minute, second, usecond) < 0)
                        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;
 }
 
-/* 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 *
 time_repr(PyDateTime_Time *self)
@@ -3536,6 +3709,7 @@ time_repr(PyDateTime_Time *self)
        int m = TIME_GET_MINUTE(self);
        int s = TIME_GET_SECOND(self);
        int us = TIME_GET_MICROSECOND(self);
+       PyObject *result = NULL;
 
        if (us)
                PyOS_snprintf(buffer, sizeof(buffer),
@@ -3546,7 +3720,10 @@ time_repr(PyDateTime_Time *self)
        else
                PyOS_snprintf(buffer, sizeof(buffer),
                              "%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 *
@@ -3558,7 +3735,8 @@ time_str(PyDateTime_Time *self)
 static PyObject *
 time_isoformat(PyDateTime_Time *self)
 {
-       char buffer[100];
+       char buf[100];
+       PyObject *result;
        /* Reuse the time format code from the datetime type. */
        PyDateTime_DateTime datetime;
        PyDateTime_DateTime *pdatetime = &datetime;
@@ -3568,8 +3746,19 @@ time_isoformat(PyDateTime_Time *self)
               self->data,
               _PyDateTime_TIME_DATASIZE);
 
-       isoformat_time(pdatetime, buffer, sizeof(buffer));
-       return PyString_FromString(buffer);
+       isoformat_time(pdatetime, buf, sizeof(buf));
+       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 *
@@ -3602,12 +3791,13 @@ time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
        return result;
 }
 
-/* Miscellaneous methods. */
+/*
+ * Miscellaneous methods.
+ */
 
 /* 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
  * PyInstance_Check returns true, but these aren't old-style classes.
- * Note that this routine handles all comparisons for time and timetz.
  */
 static PyObject *
 time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
@@ -3685,7 +3875,7 @@ time_hash(PyDateTime_Time *self)
                        int minute;
 
                        assert(n == OFFSET_AWARE);
-                       assert(PyTimeTZ_Check(self));
+                       assert(self->hastzinfo);
                        hour = divmod(TIME_GET_HOUR(self) * 60 +
                                        TIME_GET_MINUTE(self) - offset,
                                      60,
@@ -3693,7 +3883,8 @@ time_hash(PyDateTime_Time *self)
                        if (0 <= hour && hour < 24)
                                temp = new_time(hour, minute,
                                                TIME_GET_SECOND(self),
-                                               TIME_GET_MICROSECOND(self));
+                                               TIME_GET_MICROSECOND(self),
+                                               Py_None);
                        else
                                temp = Py_BuildValue("iiii",
                                           hour, minute,
@@ -3717,12 +3908,13 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
        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;
 
-       if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiii:replace",
+       if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
                                          time_kws,
-                                         &hh, &mm, &ss, &us))
+                                         &hh, &mm, &ss, &us, &tzinfo))
                return NULL;
-       tuple = Py_BuildValue("iiii", hh, mm, ss, us);
+       tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
        if (tuple == NULL)
                return NULL;
        clone = time_new(self->ob_type, tuple, NULL);
@@ -3733,408 +3925,55 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
 static int
 time_nonzero(PyDateTime_Time *self)
 {
-       return TIME_GET_HOUR(self) ||
-              TIME_GET_MINUTE(self) ||
-              TIME_GET_SECOND(self) ||
-              TIME_GET_MICROSECOND(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->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,
-        PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm].")},
+/*
+ * Pickle support.  Quite a maze!
+ */
 
-       {"strftime",    (PyCFunction)time_strftime,     METH_KEYWORDS,
-        PyDoc_STR("format -> strftime() style string.")},
+/* 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 *
+time_getstate(PyDateTime_Time *self)
+{
+       PyObject *basestate;
+       PyObject *result = NULL;
 
-       {"replace",     (PyCFunction)time_replace,      METH_KEYWORDS,
-        PyDoc_STR("Return datetime with new specified fields.")},
-       {NULL,  NULL}
-};
+       basestate =  PyString_FromStringAndSize((char *)self->data,
+                                               _PyDateTime_TIME_DATASIZE);
+       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[] =
-PyDoc_STR("Basic time type.");
-
-static PyNumberMethods time_as_number = {
-       0,                                      /* nb_add */
-       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;
+static PyObject *
+time_setstate(PyDateTime_Time *self, PyObject *state)
+{
+       PyObject *basestate;
+       PyObject *tzinfo = Py_None;
 
        if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
                               &PyString_Type, &basestate,
@@ -4146,33 +3985,41 @@ timetz_setstate(PyDateTime_TimeTZ *self, PyObject *state)
                                "bad argument to time.__setstate__");
                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,
               PyString_AsString(basestate),
               _PyDateTime_TIME_DATASIZE);
        self->hashcode = -1;
-       Py_INCREF(tzinfo);
-       Py_XDECREF(self->tzinfo);
-       self->tzinfo = tzinfo;
+       if (self->hastzinfo) {
+               Py_INCREF(tzinfo);
+               Py_XDECREF(self->tzinfo);
+               self->tzinfo = tzinfo;
+       }
        Py_INCREF(Py_None);
        return Py_None;
 }
 
 static PyObject *
-timetz_pickler(PyObject *module, PyDateTime_TimeTZ *timetz)
+time_pickler(PyObject *module, PyDateTime_Time *time)
 {
        PyObject *state;
        PyObject *result = NULL;
 
-       if (! PyTimeTZ_CheckExact(timetz)) {
+       if (! PyTime_CheckExact(time)) {
                PyErr_Format(PyExc_TypeError,
-                            "bad type passed to timetz pickler: %s",
-                            timetz->ob_type->tp_name);
+                            "bad type passed to time pickler: %s",
+                            time->ob_type->tp_name);
                return NULL;
        }
-       state = timetz_getstate(timetz);
+       state = time_getstate(time);
        if (state) {
                result = Py_BuildValue("O(O)",
-                                      timetz_unpickler_object,
+                                      time_unpickler_object,
                                       state);
                Py_DECREF(state);
        }
@@ -4180,55 +4027,70 @@ timetz_pickler(PyObject *module, PyDateTime_TimeTZ *timetz)
 }
 
 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) {
                PyObject *res;
 
-               self->tzinfo = NULL;
-               res = timetz_setstate(self, arg);
+               self->tzinfo = Py_None;
+               Py_INCREF(self->tzinfo);
+               self->hastzinfo = (char)1;      /* true */
+               res = time_setstate(self, arg);
                if (res == NULL) {
                        Py_DECREF(self);
                        return NULL;
                }
                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;
 }
 
-static PyMethodDef timetz_methods[] = {
-       {"isoformat",   (PyCFunction)timetz_isoformat,  METH_KEYWORDS,
+static PyMethodDef time_methods[] = {
+       {"isoformat",   (PyCFunction)time_isoformat,    METH_KEYWORDS,
         PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
                   "[+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).")},
 
-       {"tzname",      (PyCFunction)timetz_tzname,     METH_NOARGS,
+       {"tzname",      (PyCFunction)time_tzname,       METH_NOARGS,
         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).")},
 
-       {"replace",     (PyCFunction)timetz_replace,    METH_KEYWORDS,
-        PyDoc_STR("Return timetz with new specified fields.")},
+       {"replace",     (PyCFunction)time_replace,      METH_KEYWORDS,
+        PyDoc_STR("Return time with new specified fields.")},
 
-       {"__setstate__", (PyCFunction)timetz_setstate,  METH_O,
+       {"__setstate__", (PyCFunction)time_setstate,    METH_O,
         PyDoc_STR("__setstate__(state)")},
 
-       {"__getstate__", (PyCFunction)timetz_getstate,  METH_NOARGS,
+       {"__getstate__", (PyCFunction)time_getstate,    METH_NOARGS,
         PyDoc_STR("__getstate__() -> state")},
        {NULL,  NULL}
-
 };
 
-static char timetz_doc[] =
+static char time_doc[] =
 PyDoc_STR("Time type.");
 
-static PyNumberMethods timetz_as_number = {
+static PyNumberMethods time_as_number = {
        0,                                      /* nb_add */
        0,                                      /* nb_subtract */
        0,                                      /* nb_multiply */
@@ -4239,50 +4101,50 @@ static PyNumberMethods timetz_as_number = {
        0,                                      /* nb_negative */
        0,                                      /* nb_positive */
        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)
        0,                                      /* ob_size */
        "datetime.time",                        /* tp_name */
-       sizeof(PyDateTime_TimeTZ),              /* tp_basicsize */
+       sizeof(PyDateTime_Time),                /* tp_basicsize */
        0,                                      /* tp_itemsize */
-       (destructor)timetz_dealloc,             /* tp_dealloc */
+       (destructor)time_dealloc,               /* tp_dealloc */
        0,                                      /* tp_print */
        0,                                      /* tp_getattr */
        0,                                      /* tp_setattr */
        0,                                      /* tp_compare */
-       (reprfunc)timetz_repr,                  /* tp_repr */
-       &timetz_as_number,                      /* tp_as_number */
+       (reprfunc)time_repr,                    /* tp_repr */
+       &time_as_number,                        /* tp_as_number */
        0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
-       0,                                      /* tp_hash */
+       (hashfunc)time_hash,                    /* tp_hash */
        0,                                      /* tp_call */
-       0,                                      /* tp_str */
+       (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 */
-       timetz_doc,                             /* tp_doc */
+       time_doc,                               /* tp_doc */
        0,                                      /* tp_traverse */
        0,                                      /* tp_clear */
-       0,                                      /* tp_richcompare */
+       (richcmpfunc)time_richcompare,          /* tp_richcompare */
        0,                                      /* tp_weaklistoffset */
        0,                                      /* tp_iter */
        0,                                      /* tp_iternext */
-       timetz_methods,                         /* tp_methods */
+       time_methods,                           /* tp_methods */
        0,                                      /* tp_members */
-       timetz_getset,                          /* tp_getset */
-       &PyDateTime_TimeType,                   /* tp_base */
+       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 */
-       timetz_new,                             /* tp_new */
+       time_new,                               /* tp_new */
        _PyObject_Del,                          /* tp_free */
 };
 
@@ -4789,11 +4651,11 @@ datetimetz_utctimetuple(PyDateTime_DateTimeTZ *self)
 static PyObject *
 datetimetz_gettimetz(PyDateTime_DateTimeTZ *self)
 {
-       return new_timetz(DATE_GET_HOUR(self),
-                         DATE_GET_MINUTE(self),
-                         DATE_GET_SECOND(self),
-                         DATE_GET_MICROSECOND(self),
-                         self->tzinfo);
+       return new_time(DATE_GET_HOUR(self),
+                       DATE_GET_MINUTE(self),
+                       DATE_GET_SECOND(self),
+                       DATE_GET_MICROSECOND(self),
+                       self->tzinfo);
 }
 
 /*
@@ -5019,8 +4881,8 @@ static PyMethodDef module_methods[] = {
        {"_date_unpickler",     (PyCFunction)date_unpickler,    METH_O, NULL},
        {"_datetimetz_pickler", (PyCFunction)datetimetz_pickler,METH_O, NULL},
        {"_datetimetz_unpickler",(PyCFunction)datetimetz_unpickler,METH_O, NULL},
-       {"_timetz_pickler",     (PyCFunction)timetz_pickler,    METH_O, NULL},
-       {"_timetz_unpickler",   (PyCFunction)timetz_unpickler,  METH_O, NULL},
+       {"_time_pickler",       (PyCFunction)time_pickler,      METH_O, NULL},
+       {"_time_unpickler",     (PyCFunction)time_unpickler,    METH_O, NULL},
        {"_tzinfo_pickler",     (PyCFunction)tzinfo_pickler,    METH_O, NULL},
        {"_tzinfo_unpickler",   (PyCFunction)tzinfo_unpickler,  METH_NOARGS,
         NULL},
@@ -5054,8 +4916,6 @@ initdatetime(void)
                return;
        if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
                return;
-       if (PyType_Ready(&PyDateTime_TimeTZType) < 0)
-               return;
        if (PyType_Ready(&PyDateTime_DateTimeTZType) < 0)
                return;
 
@@ -5079,15 +4939,15 @@ initdatetime(void)
                Py_DECREF(x);
                Py_DECREF(pickler);
 
-               pickler = PyObject_GetAttrString(m, "_timetz_pickler");
+               pickler = PyObject_GetAttrString(m, "_time_pickler");
                if (pickler == NULL) return;
-               timetz_unpickler_object = PyObject_GetAttrString(m,
-                                               "_timetz_unpickler");
-               if (timetz_unpickler_object == NULL) return;
+               time_unpickler_object = PyObject_GetAttrString(m,
+                                               "_time_unpickler");
+               if (time_unpickler_object == NULL) return;
                x = PyObject_CallMethod(copyreg, "pickle", "OOO",
-                                       &PyDateTime_TimeTZType,
+                                       &PyDateTime_TimeType,
                                        pickler,
-                                       timetz_unpickler_object);
+                                       time_unpickler_object);
                if (x == NULL) return;
                Py_DECREF(x);
                Py_DECREF(pickler);
@@ -5160,15 +5020,15 @@ initdatetime(void)
                return;
        Py_DECREF(x);
 
-       /* timetz values */
-       d = PyDateTime_TimeTZType.tp_dict;
+       /* time values */
+       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)
                return;
        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)
                return;
        Py_DECREF(x);
@@ -5211,8 +5071,8 @@ initdatetime(void)
        Py_INCREF(&PyDateTime_TZInfoType);
        PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
 
-       Py_INCREF(&PyDateTime_TimeTZType);
-       PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeTZType);
+       Py_INCREF(&PyDateTime_TimeType);
+       PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
 
        Py_INCREF(&PyDateTime_DateTimeTZType);
        PyModule_AddObject(m, "datetime",