Index: Doc/lib/libdatetime.tex =================================================================== --- Doc/lib/libdatetime.tex (revision 54295) +++ Doc/lib/libdatetime.tex (working copy) @@ -368,6 +368,10 @@ \lineii{\var{date1} < \var{date2}} {\var{date1} is considered less than \var{date2} when \var{date1} precedes \var{date2} in time. (4)} + + \lineii{\var{datetime} in \var{date}} + {\var{datetime} occurs on \var{date}. This is a shortcut for + \code{datetime.date() == date}. \versionadded{2.6}} \end{tableii} Index: Lib/test/test_datetime.py =================================================================== --- Lib/test/test_datetime.py (revision 54295) +++ Lib/test/test_datetime.py (working copy) @@ -945,6 +945,29 @@ self.assertRaises(TypeError, lambda: badarg < t1) self.assertRaises(TypeError, lambda: badarg > t1) self.assertRaises(TypeError, lambda: badarg >= t1) + + def test_contains_datetime(self): + d = self.theclass(2, 3, 4) + + dt1 = datetime(2, 3, 4, 0, 0, 0) + self.failUnless(dt1 in d) + + dt2 = datetime(2, 3, 4, 5, 6, 7) + self.failUnless(dt2 in d) + + dt3 = datetime(2, 3, 5, 0, 0, 0) + self.failUnless(dt3 not in d) + + # These should all raise TypeErrors + for obj in [timedelta(), time(), date(2, 3, 4)]: + self.assertRaises(TypeError, d.__contains__, obj) + + # ...but subclasses of datetime are alright + class DT(datetime): + pass + + dts = DT(2, 3, 4, 0, 0, 1) + self.failUnless(dts in d) def test_mixed_compare(self): our = self.theclass(2000, 4, 5) @@ -1375,6 +1398,13 @@ self.failUnless(not t2 <= t1) self.assertEqual(cmp(t1, t2), -1) self.assertEqual(cmp(t2, t1), 1) + + def test_contains_datetime(self): + # Override this (inherited from TestDate); datetime + # objects can't "contain" anything. + + dt = self.theclass(2003, 2, 7, 16, 48, 37) + self.assertRaises(TypeError, dt.__contains__, dt) # A helper for timestamp constructor tests. Index: Modules/datetimemodule.c =================================================================== --- Modules/datetimemodule.c (revision 54295) +++ Modules/datetimemodule.c (working copy) @@ -2529,6 +2529,19 @@ return diff_to_bool(diff, op); } +static int +date_contains(PyDateTime_Date *self, PyObject *other) +{ + if (!PyDateTime_Check(other)) { + PyErr_SetString(PyExc_TypeError, "dates can only contain datetimes"); + return -1; + } + + return GET_YEAR(self) == GET_YEAR(other) && + GET_MONTH(self) == GET_MONTH(other) && + GET_DAY(self) == GET_DAY(other); +} + static PyObject * date_timetuple(PyDateTime_Date *self) { @@ -2680,6 +2693,19 @@ 0, /* nb_nonzero */ }; +static PySequenceMethods date_as_sequence = { + 0, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + 0, /* sq_item */ + 0, /* sq_slice */ + 0, /* sq_ass_item */ + 0, /* sq_ass_slice */ + (objobjproc)date_contains, /* sq_contains */ + 0, /* sq_inplace_concat */ + 0, /* sq_inplace_repeat */ +}; + static PyTypeObject PyDateTime_DateType = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ @@ -2693,7 +2719,7 @@ 0, /* tp_compare */ (reprfunc)date_repr, /* tp_repr */ &date_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ + &date_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)date_hash, /* tp_hash */ 0, /* tp_call */ @@ -4204,6 +4230,15 @@ return NULL; } +static int +datetime_contains(PyDateTime_DateTime *self, PyObject *other) +{ + PyErr_Format(PyExc_TypeError, + "argument of type '%.200s' is not iterable", + self->ob_type->tp_name); + return -1; +} + static long datetime_hash(PyDateTime_DateTime *self) { @@ -4558,6 +4593,20 @@ 0, /* nb_nonzero */ }; +/* Don't want to inherit sq_contains from date */ +static PySequenceMethods datetime_as_sequence = { + 0, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + 0, /* sq_item */ + 0, /* sq_slice */ + 0, /* sq_ass_item */ + 0, /* sq_ass_slice */ + (objobjproc)datetime_contains, /* sq_contains */ + 0, /* sq_inplace_concat */ + 0, /* sq_inplace_repeat */ +}; + statichere PyTypeObject PyDateTime_DateTimeType = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ @@ -4571,7 +4620,7 @@ 0, /* tp_compare */ (reprfunc)datetime_repr, /* tp_repr */ &datetime_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ + &datetime_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)datetime_hash, /* tp_hash */ 0, /* tp_call */