[Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.37,1.38 test_datetime.py,1.23,1.24
Tim Peters
tim_one@users.sourceforge.net
Sun, 03 Mar 2002 22:10:17 -0800
Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory usw-pr-cvs1:/tmp/cvs-serv26196
Modified Files:
datetime.py test_datetime.py
Log Message:
Fixed two bugs in datetime.__cmp__:
1. Shallow. When the tzoffsets matched, it forgot to compare
microseconds.
2. Not so shallow. When the tzoffsets didn't match, it reverted to
comparing timestamps, but an IEEE double doesn't have enough
precision to avoid mapping distinct datetimes onto the same timestamp.
It takes about 38 bits to distinguish the individual seconds across
10000 years, leaving only about 53-38 = 15 bits to distinguish the
microseconds. As a result, non-equal datetimes could compare equal,
especially for years near MAXYEAR.
Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.37
retrieving revision 1.38
diff -C2 -d -r1.37 -r1.38
*** datetime.py 4 Mar 2002 03:01:14 -0000 1.37
--- datetime.py 4 Mar 2002 06:10:15 -0000 1.38
***************
*** 578,592 ****
"Three-way comparison."
if isinstance(other, datetime):
! if other.__tzoffset == self.__tzoffset:
y, m, d = self.__year, self.__month, self.__day
! hh, mm, ss = self.__hour, self.__minute, self.__second
! tz = self.__tzoffset
y2, m2, d2 = other.__year, other.__month, other.__day
! hh2, mm2, ss2 = other.__hour, other.__minute, other.__second
! tz2 = other.__tzoffset
! return cmp((y, m, d, hh, mm, ss, tz),
! (y2, m2, d2, hh2, mm2, ss2, tz2))
else:
! return cmp(self._mktime(), other._mktime())
else:
raise TypeError, ("can't compare datetime to %s instance" %
--- 578,593 ----
"Three-way comparison."
if isinstance(other, datetime):
! if self.__tzoffset == other.__tzoffset:
y, m, d = self.__year, self.__month, self.__day
! H, M = self.__hour, self.__minute
y2, m2, d2 = other.__year, other.__month, other.__day
! H2, M2 = other.__hour, other.__minute
else:
! y, m, d, H, M = self._utc_ymdHM()
! y2, m2, d2, H2, M2 = other._utc_ymdHM()
! return cmp((y, m, d, H, M,
! self.__second, self.__microsecond),
! (y2, m2, d2, H2, M2,
! other.__second, other.__microsecond))
else:
raise TypeError, ("can't compare datetime to %s instance" %
Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.23
retrieving revision 1.24
diff -C2 -d -r1.23 -r1.24
*** test_datetime.py 4 Mar 2002 01:24:50 -0000 1.23
--- test_datetime.py 4 Mar 2002 06:10:15 -0000 1.24
***************
*** 7,11 ****
import unittest
! from datetime import datetime, timedelta
class TestDateTime(unittest.TestCase):
--- 7,11 ----
import unittest
! from datetime import datetime, timedelta, MINYEAR, MAXYEAR
class TestDateTime(unittest.TestCase):
***************
*** 42,47 ****
self.assert_(dt2 > dt3)
def test_ordinal_conversions(self):
! from datetime import _ymd2ord, _ord2ymd, MINYEAR, MAXYEAR
# Check some fixed values.
--- 42,66 ----
self.assert_(dt2 > dt3)
+ # Make sure comparison doesn't forget microseconds, and isn't done
+ # via comparing a float timestamp (an IEEE double doesn't have enough
+ # precision to span microsecond resolution across years 1 thru 9999,
+ # so comparing via timestamp necessarily calls some distinct values
+ # equal).
+ dt1 = datetime.new(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0)
+ us = timedelta(microseconds=1)
+ dt2 = dt1 + us
+ self.assertEqual(dt2 - dt1, us)
+ self.assert_(dt1 < dt2)
+
+ # Again, but mix timezones.
+ dt1 = datetime.new(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60)
+ dt2 = datetime.new(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0)
+ self.assert_(dt1 == dt2)
+ dt2 += us
+ self.assertEqual(dt2 - dt1, us)
+ self.assert_(dt1 < dt2)
+
def test_ordinal_conversions(self):
! from datetime import _ymd2ord, _ord2ymd
# Check some fixed values.
***************
*** 78,82 ****
def test_bad_constructor_arguments(self):
- from datetime import MINYEAR, MAXYEAR
# bad years
datetime(MINYEAR, 1, 1) # no exception
--- 97,100 ----