datetime.datetime and datetime.time can now be subclassed in Python.  Brr.
diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py
index 51b5f4f..c4978f3 100644
--- a/Lib/test/test_datetime.py
+++ b/Lib/test/test_datetime.py
@@ -479,37 +479,6 @@
         dt2 = dt - delta
         self.assertEqual(dt2, dt - days)
 
-    def test_subclass_date(self):
-
-        # XXX When datetime becomes usably subclassable, uncomment the
-        # XXX "self.theclass" lines and move this into TestDate.
-        # class C(self.theclass):
-        class C(date):
-            theAnswer = 42
-
-            def __new__(cls, *args, **kws):
-                temp = kws.copy()
-                extra = temp.pop('extra')
-                # result = self.theclass.__new__(cls, *args, **temp)
-                result = date.__new__(cls, *args, **temp)
-                result.extra = extra
-                return result
-
-            def newmeth(self, start):
-                return start + self.year + self.month
-
-        args = 2003, 4, 14
-
-        # dt1 = self.theclass(*args)
-        dt1 = date(*args)
-        dt2 = C(*args, **{'extra': 7})
-
-        self.assertEqual(dt2.__class__, C)
-        self.assertEqual(dt2.theAnswer, 42)
-        self.assertEqual(dt2.extra, 7)
-        self.assertEqual(dt1.toordinal(), dt2.toordinal())
-        self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month - 7)
-
 class TestDate(HarmlessMixedComparison):
     # Tests here should pass for both dates and datetimes, except for a
     # few tests that TestDateTime overrides.
@@ -1002,6 +971,32 @@
         base = cls(2000, 2, 29)
         self.assertRaises(ValueError, base.replace, year=2001)
 
+    def test_subclass_date(self):
+
+        class C(self.theclass):
+            theAnswer = 42
+
+            def __new__(cls, *args, **kws):
+                temp = kws.copy()
+                extra = temp.pop('extra')
+                result = self.theclass.__new__(cls, *args, **temp)
+                result.extra = extra
+                return result
+
+            def newmeth(self, start):
+                return start + self.year + self.month
+
+        args = 2003, 4, 14
+
+        dt1 = self.theclass(*args)
+        dt2 = C(*args, **{'extra': 7})
+
+        self.assertEqual(dt2.__class__, C)
+        self.assertEqual(dt2.theAnswer, 42)
+        self.assertEqual(dt2.extra, 7)
+        self.assertEqual(dt1.toordinal(), dt2.toordinal())
+        self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month - 7)
+
 
 #############################################################################
 # datetime tests
@@ -1426,6 +1421,33 @@
         alsobog = AlsoBogus()
         self.assertRaises(ValueError, dt.astimezone, alsobog) # also naive
 
+    def test_subclass_datetime(self):
+
+        class C(self.theclass):
+            theAnswer = 42
+
+            def __new__(cls, *args, **kws):
+                temp = kws.copy()
+                extra = temp.pop('extra')
+                result = self.theclass.__new__(cls, *args, **temp)
+                result.extra = extra
+                return result
+
+            def newmeth(self, start):
+                return start + self.year + self.month + self.second
+
+        args = 2003, 4, 14, 12, 13, 41
+
+        dt1 = self.theclass(*args)
+        dt2 = C(*args, **{'extra': 7})
+
+        self.assertEqual(dt2.__class__, C)
+        self.assertEqual(dt2.theAnswer, 42)
+        self.assertEqual(dt2.extra, 7)
+        self.assertEqual(dt1.toordinal(), dt2.toordinal())
+        self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month +
+                                          dt1.second - 7)
+
 class TestTime(HarmlessMixedComparison):
 
     theclass = time
@@ -1660,6 +1682,32 @@
         self.assertRaises(ValueError, base.replace, second=100)
         self.assertRaises(ValueError, base.replace, microsecond=1000000)
 
+    def test_subclass_time(self):
+
+        class C(self.theclass):
+            theAnswer = 42
+
+            def __new__(cls, *args, **kws):
+                temp = kws.copy()
+                extra = temp.pop('extra')
+                result = self.theclass.__new__(cls, *args, **temp)
+                result.extra = extra
+                return result
+
+            def newmeth(self, start):
+                return start + self.hour + self.second
+
+        args = 4, 5, 6
+
+        dt1 = self.theclass(*args)
+        dt2 = C(*args, **{'extra': 7})
+
+        self.assertEqual(dt2.__class__, C)
+        self.assertEqual(dt2.theAnswer, 42)
+        self.assertEqual(dt2.extra, 7)
+        self.assertEqual(dt1.isoformat(), dt2.isoformat())
+        self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.second - 7)
+
 # A mixin for classes with a tzinfo= argument.  Subclasses must define
 # theclass as a class atribute, and theclass(1, 1, 1, tzinfo=whatever)
 # must be legit (which is true for time and datetime).
@@ -2042,6 +2090,32 @@
         t2 = t2.replace(tzinfo=Varies())
         self.failUnless(t1 < t2)  # t1's offset counter still going up
 
+    def test_subclass_timetz(self):
+
+        class C(self.theclass):
+            theAnswer = 42
+
+            def __new__(cls, *args, **kws):
+                temp = kws.copy()
+                extra = temp.pop('extra')
+                result = self.theclass.__new__(cls, *args, **temp)
+                result.extra = extra
+                return result
+
+            def newmeth(self, start):
+                return start + self.hour + self.second
+
+        args = 4, 5, 6, 500, FixedOffset(-300, "EST", 1)
+
+        dt1 = self.theclass(*args)
+        dt2 = C(*args, **{'extra': 7})
+
+        self.assertEqual(dt2.__class__, C)
+        self.assertEqual(dt2.theAnswer, 42)
+        self.assertEqual(dt2.extra, 7)
+        self.assertEqual(dt1.utcoffset(), dt2.utcoffset())
+        self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.second - 7)
+
 
 # Testing datetime objects with a non-None tzinfo.
 
@@ -2625,6 +2699,32 @@
         t2 = t2.replace(tzinfo=Varies())
         self.failUnless(t1 < t2)  # t1's offset counter still going up
 
+    def test_subclass_datetimetz(self):
+
+        class C(self.theclass):
+            theAnswer = 42
+
+            def __new__(cls, *args, **kws):
+                temp = kws.copy()
+                extra = temp.pop('extra')
+                result = self.theclass.__new__(cls, *args, **temp)
+                result.extra = extra
+                return result
+
+            def newmeth(self, start):
+                return start + self.hour + self.year
+
+        args = 2002, 12, 31, 4, 5, 6, 500, FixedOffset(-300, "EST", 1)
+
+        dt1 = self.theclass(*args)
+        dt2 = C(*args, **{'extra': 7})
+
+        self.assertEqual(dt2.__class__, C)
+        self.assertEqual(dt2.theAnswer, 42)
+        self.assertEqual(dt2.extra, 7)
+        self.assertEqual(dt1.utcoffset(), dt2.utcoffset())
+        self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.year - 7)
+
 # Pain to set up DST-aware tzinfo classes.
 
 def first_sunday_on_or_after(dt):
diff --git a/Misc/NEWS b/Misc/NEWS
index 6e8cae6..e182845 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -26,6 +26,9 @@
 Extension modules
 -----------------
 
+- The datetime.datetime and datetime.time classes are now properly
+  subclassable.
+
 - _tkinter.{get|set}busywaitinterval was added.
 
 - itertools.islice() now accepts stop=None as documented.
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index d25eb70..3679338 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -1235,38 +1235,42 @@
 }
 
 /* ---------------------------------------------------------------------------
- * Basic object allocation.  These allocate Python objects of the right
- * size and type, and do the Python object-initialization bit.  If there's
- * not enough memory, they return NULL after setting MemoryError.  All
- * data members remain uninitialized trash.
+ * Basic object allocation:  tp_alloc implementatiosn.  These allocate
+ * Python objects of the right size and type, and do the Python object-
+ * initialization bit.  If there's not enough memory, they return NULL after
+ * setting MemoryError.  All data members remain uninitialized trash.
+ *
+ * We abuse the tp_alloc "nitems" argument to communicate whether a tzinfo
+ * member is needed.  This is ugly.
  */
-static PyDateTime_Time *
-alloc_time(int aware)
-{
-	PyDateTime_Time *self;
 
-	self = (PyDateTime_Time *)
+static PyObject *
+time_alloc(PyTypeObject *type, int aware)
+{
+	PyObject *self;
+
+	self = (PyObject *)
 		PyObject_MALLOC(aware ?
 				sizeof(PyDateTime_Time) :
 				sizeof(_PyDateTime_BaseTime));
 	if (self == NULL)
-		return (PyDateTime_Time *)PyErr_NoMemory();
-	PyObject_INIT(self, &PyDateTime_TimeType);
+		return (PyObject *)PyErr_NoMemory();
+	PyObject_INIT(self, type);
 	return self;
 }
 
-static PyDateTime_DateTime *
-alloc_datetime(int aware)
+static PyObject *
+datetime_alloc(PyTypeObject *type, int aware)
 {
-	PyDateTime_DateTime *self;
+	PyObject *self;
 
-	self = (PyDateTime_DateTime *)
+	self = (PyObject *)
 		PyObject_MALLOC(aware ?
 				sizeof(PyDateTime_DateTime) :
 				sizeof(_PyDateTime_BaseDateTime));
 	if (self == NULL)
-		return (PyDateTime_DateTime *)PyErr_NoMemory();
-	PyObject_INIT(self, &PyDateTime_DateTimeType);
+		return (PyObject *)PyErr_NoMemory();
+	PyObject_INIT(self, type);
 	return self;
 }
 
@@ -1302,17 +1306,17 @@
 }
 
 #define new_date(year, month, day) \
-	(new_date_ex(year, month, day, &PyDateTime_DateType))
+	new_date_ex(year, month, day, &PyDateTime_DateType)
 
 /* Create a datetime instance with no range checking. */
 static PyObject *
-new_datetime(int year, int month, int day, int hour, int minute,
-	     int second, int usecond, PyObject *tzinfo)
+new_datetime_ex(int year, int month, int day, int hour, int minute,
+	     int second, int usecond, PyObject *tzinfo, PyTypeObject *type)
 {
 	PyDateTime_DateTime *self;
 	char aware = tzinfo != Py_None;
 
-	self = alloc_datetime(aware);
+	self = (PyDateTime_DateTime *) (type->tp_alloc(type, aware));
 	if (self != NULL) {
 		self->hastzinfo = aware;
 		set_date_fields((PyDateTime_Date *)self, year, month, day);
@@ -1328,14 +1332,19 @@
 	return (PyObject *)self;
 }
 
+#define new_datetime(y, m, d, hh, mm, ss, us, tzinfo)		\
+	new_datetime_ex(y, m, d, hh, mm, ss, us, tzinfo,	\
+			&PyDateTime_DateTimeType)
+
 /* Create a time instance with no range checking. */
 static PyObject *
-new_time(int hour, int minute, int second, int usecond, PyObject *tzinfo)
+new_time_ex(int hour, int minute, int second, int usecond,
+	    PyObject *tzinfo, PyTypeObject *type)
 {
 	PyDateTime_Time *self;
 	char aware = tzinfo != Py_None;
 
-	self = alloc_time(aware);
+	self = (PyDateTime_Time *) (type->tp_alloc(type, aware));
 	if (self != NULL) {
 		self->hastzinfo = aware;
 		self->hashcode = -1;
@@ -1351,6 +1360,9 @@
 	return (PyObject *)self;
 }
 
+#define new_time(hh, mm, ss, us, tzinfo)		\
+	new_time_ex(hh, mm, ss, us, tzinfo, &PyDateTime_TimeType)
+
 /* Create a timedelta instance.  Normalize the members iff normalize is
  * true.  Passing false is a speed optimization, if you know for sure
  * that seconds and microseconds are already in their proper ranges.  In any
@@ -3014,7 +3026,8 @@
 			}
 		}
 		aware = (char)(tzinfo != Py_None);
-		me = alloc_time(aware);
+		me = (PyDateTime_Time *) time_alloc(&PyDateTime_TimeType,
+						    aware);
 		if (me != NULL) {
 			char *pdata = PyString_AS_STRING(state);
 
@@ -3036,7 +3049,8 @@
 			return NULL;
 		if (check_tzinfo_subclass(tzinfo) < 0)
 			return NULL;
-		self = new_time(hour, minute, second, usecond, tzinfo);
+		self = new_time_ex(hour, minute, second, usecond, tzinfo,
+				   type);
 	}
 	return self;
 }
@@ -3439,7 +3453,7 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	0,					/* tp_init */
-	0,					/* tp_alloc */
+	time_alloc,				/* tp_alloc */
 	time_new,				/* tp_new */
 	0,					/* tp_free */
 };
@@ -3534,7 +3548,9 @@
 			}
 		}
 		aware = (char)(tzinfo != Py_None);
-		me = alloc_datetime(aware);
+		me = (PyDateTime_DateTime *) datetime_alloc(
+						&PyDateTime_DateTimeType,
+				     		aware);
 		if (me != NULL) {
 			char *pdata = PyString_AS_STRING(state);
 
@@ -3558,9 +3574,9 @@
 			return NULL;
 		if (check_tzinfo_subclass(tzinfo) < 0)
 			return NULL;
-		self = new_datetime(year, month, day,
-				    hour, minute, second, usecond,
-				    tzinfo);
+		self = new_datetime_ex(year, month, day,
+				    	hour, minute, second, usecond,
+				    	tzinfo, type);
 	}
 	return self;
 }
@@ -4460,7 +4476,7 @@
 	0,					/* tp_descr_set */
 	0,					/* tp_dictoffset */
 	0,					/* tp_init */
-	0,					/* tp_alloc */
+	datetime_alloc,				/* tp_alloc */
 	datetime_new,				/* tp_new */
 	0,					/* tp_free */
 };