[Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.51,1.52 test_datetime.py,1.36,1.37

Guido van Rossum gvanrossum@users.sourceforge.net
Tue, 05 Mar 2002 06:14:50 -0800


Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory usw-pr-cvs1:/tmp/cvs-serv32276

Modified Files:
	datetime.py test_datetime.py 
Log Message:
A somewhat yucky but I think necessary change: introduce a separate
date class.  This implements all the date shuffling; the datetime
class then subclasses this and adds more precision and tzoffset
fiddling.

It's yucky because there's a fair amount of code duplication, alas --
this can probably be reduced by thinking more about which interfaces
are needed.

It's also necessary because the more I think about it, the more we
need a succession of types:

- date -- for calendrical computations
- xxxx -- for date+time computations without timezone awareness
- yyyy -- local-timezone-and-DST-aware date+time computations
- zzzz -- UTC date+time computations
- datetime -- generalized timezone-and-DST-aware date+time computations

I'll try to clean this up some more after my shower.



Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.51
retrieving revision 1.52
diff -C2 -d -r1.51 -r1.52
*** datetime.py	5 Mar 2002 09:12:44 -0000	1.51
--- datetime.py	5 Mar 2002 14:14:48 -0000	1.52
***************
*** 1,3 ****
! """Concrete date/time type -- prototype implemented in Python.
  
  See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
--- 1,3 ----
! """Concrete date/time and related types -- prototype implemented in Python.
  
  See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
***************
*** 506,511 ****
  
  
! class datetime(basetime):
!     """Concrete date/time type.
  
      Constructors:
--- 506,751 ----
  
  
! class date(basetime):
!     """Concrete date type.
! 
!     Constructors:
! 
!     __init__()
!     today()
!     fromordinal()
! 
!     Operators:
! 
!     __repr__, __str__
!     __cmp__, __hash__
!     __add__, __radd__, __sub__ (add/radd only with timedelta arg)
! 
!     Methods:
! 
!     timetuple(), utctimetuple()
!     toordinal()
!     weekday(), isoweekday(), isocalendar()
!     isoformat()
! 
!     Properties (readonly):
!     year, month, day
!     """
! 
!     def __init__(self, year, month, day):
!         """Constructor.
! 
!         Arguments:
! 
!         year, month, day (required, base 1)
!         """
!         if not MINYEAR <= year <= MAXYEAR:
!             raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR),
!                              year)
!         if not 1 <= month <= 12:
!             raise ValueError('month must be in 1..12', month)
!         dim = _days_in_month(month, year)
!         if not 1 <= day <= dim:
!             raise ValueError('day must be in 1..%d' % dim, day)
!         self.__year = year
!         self.__month = month
!         self.__day = day
! 
!     # Additional constructors
! 
!     def fromtimestamp(cls, t):
!         "Construct a date from a POSIX timestamp (like time.time())."
!         y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
!         us = int((t % 1.0) * 1000000)
!         if dst > 0:
!             tz = -(_time.altzone // 60)
!         else:
!             tz = -(_time.timezone // 60)
!         return cls(y, m, d)
!     fromtimestamp = classmethod(fromtimestamp)
! 
!     def today(cls):
!         "Construct a date from time.time()."
!         t = _time.time()
!         return cls.fromtimestamp(t)
!     today = classmethod(today)
! 
!     def fromordinal(cls, n):
!         """Contruct a date from a proleptic Gregorian ordinal.
! 
!         January 1 of year 1 is day 1.  Only the year, month and day are
!         non-zero in the result.
!         """
!         y, m, d = _ord2ymd(n)
!         return cls(y, m, d)
!     fromordinal = classmethod(fromordinal)
! 
!     # Conversions to string
! 
!     def __repr__(self):
!         "Convert to formal string, for repr()."
!         return "%s(%d, %d, %d)" % (self.__class__.__name__,
!                                    self.__year,
!                                    self.__month,
!                                    self.__day)
! 
!     def __str__(self):
!         "Convert to pretty string, for str()."
!         return self.isoformat()
! 
!     # Read-only field accessors
!     year = property(lambda self: self.__year,
!                     doc="year (%d-%d)" % (MINYEAR, MAXYEAR))
!     month = property(lambda self: self.__month, doc="month (1-12)")
!     day = property(lambda self: self.__day, doc="day (1-31)")
! 
!     # Standard conversions, __cmp__, __hash__ (and helpers)
! 
!     # XXX These should be done without reference to the time module
! 
!     def _mktime(self):
!         # Helper to return a POSIX-ish timestamp
!         t = tmxxx(self.__year, self.__month, self.__day)
!         return t.time()
! 
!     def timetuple(self):
!         "Return local time tuple compatible with time.localtime()."
!         return _time.localtime(self._mktime())
! 
!     def toordinal(self):
!         """Return proleptic Gregorian ordinal for the year, month and day.
! 
!         January 1 of year 1 is day 1.  Only the year, month and day values
!         contribute to the result.
!         """
!         return _ymd2ord(self.__year, self.__month, self.__day)
! 
!     def __cmp__(self, other):
!         "Three-way comparison."
!         if isinstance(other, date):
!             y, m, d = self.__year, self.__month, self.__day
!             y2, m2, d2 = other.__year, other.__month, other.__day
!             return cmp((y, m, d), (y2, m2, d2))
!         else:
!             raise TypeError, ("can't compare date to %s instance" %
!                               type(other).__name__)
! 
!     def __hash__(self):
!         "Hash."
!         # Caution:  objects that compare equal must have equal hashcodes,
!         # and two dates can be equal even if their fields aren't
!         # (due to tzoffset).  So we have to compute a UTC-normalized hash.
!         return hash((self.__year, self.__month, self.__day))
! 
!     # Formatting methods
! 
!     # XXX These shouldn't depend on time.localtime(), because that
!     # clips the usable dates to [1970 .. 2038).  At least ctime() is
!     # easily done without using strftime() -- that's better too because
!     # strftime("%c", ...) is locale specific.
! 
!     # XXX An additional question is whether ctime() should renormalize
!     # to local time, or display the time as entered (which may be
!     # confusing since it doesn't show the timezone).
! 
!     def ctime(self):
!         "Format a la ctime() in local time."
!         t = tmxxx(self.__year, self.__month, self.__day)
!         return t.ctime()
! 
!     def strftime(self, fmt):
!         "Format using strftime() in local time."
!         return _time.strftime(fmt, _time.localtime(self._mktime()))
! 
!     # Computations
! 
!     def _checkOverflow(self, year):
!         if not MINYEAR <= year <= MAXYEAR:
!             raise OverflowError("date +/-: result year %d not in %d..%d" %
!                                 (year, MINYEAR, MAXYEAR))
! 
!     def __add__(self, other):
!         "Add a date to a timedelta."
!         if isinstance(other, timedelta):
!             t = tmxxx(self.__year,
!                       self.__month,
!                       self.__day + other.days)
!             self._checkOverflow(t.year)
!             result = self.__class__(t.year, t.month, t.day)
!             return result
!         raise TypeError
!         # XXX Should be 'return NotImplemented', but there's a bug in 2.2...
! 
!     __radd__ = __add__
! 
!     timedelta_class = timedelta # Allows a subclass to override
! 
!     def __sub__(self, other):
!         """Subtract two dates, or a date and a timedelta.
! 
!         An int/long/float argument is also allowed, interpreted as seconds.
!         """
!         if isinstance(other, timedelta):
!             return self + -other
!         if isinstance(other, date):
!             days1 = self.toordinal()
!             days2 = other.toordinal()
!             return self.timedelta_class(days1 - days2)
!         return NotImplemented
! 
!     # Day-of-the-week and week-of-the-year, according to ISO
! 
!     def weekday(self):
!         "Return day of the week, where Monday == 0 ... Sunday == 6."
!         return (self.toordinal() + 6) % 7
! 
!     def isoweekday(self):
!         "Return day of the week, where Monday == 1 ... Sunday == 7."
!         # 1-Jan-0001 is a Monday
!         return self.toordinal() % 7 or 7
! 
!     def isocalendar(self):
!         """Return a 3-tuple containing ISO year, week number, and weekday.
! 
!         The first ISO week of the year is the (Mon-Sun) week
!         containing the year's first Thursday; everything rest derives
!         from that.
! 
!         The first week is 1; Monday is 1 ... Sunday is 7.
! 
!         ISO calendar algorithm taken from
!         http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
!         """
!         year = self.__year
!         week1monday = _isoweek1monday(year)
!         today = _ymd2ord(self.__year, self.__month, self.__day)
!         # Internally, week and day have origin 0
!         week, day = divmod(today - week1monday, 7)
!         if week < 0:
!             year -= 1
!             week1monday = _isoweek1monday(year)
!             week, day = divmod(today - week1monday, 7)
!         elif week >= 52:
!             if today >= _isoweek1monday(year+1):
!                 year += 1
!                 week = 0
!         return year, week+1, day+1
! 
!     def isoformat(self):
!         """Return the time formatted according to ISO.
! 
!         This is 'YYYY-MM-DD'.
! 
!         Optional argument sep specifies the separator between date and
!         time, default 'T'.
!         """
!         return "%04d-%02d-%02d" % (self.__year, self.__month, self.__day)
! 
! date.min = date(1, 1, 1)
! date.max = date(9999, 12, 31)
! date.resolution = timedelta(days=1)
! 
! 
! class datetime(date):
!     """Concrete date/time type, inheriting from date.
  
      Constructors:
***************
*** 546,557 ****
  
          """
!         if not MINYEAR <= year <= MAXYEAR:
!             raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR),
!                              year)
!         if not 1 <= month <= 12:
!             raise ValueError('month must be in 1..12', month)
!         dim = _days_in_month(month, year)
!         if not 1 <= day <= dim:
!             raise ValueError('day must be in 1..%d' % dim, day)
          if not 0 <= hour <= 23:
              raise ValueError('hour must be in 0..23', hour)
--- 786,790 ----
  
          """
!         super(datetime, self).__init__(year, month, day)
          if not 0 <= hour <= 23:
              raise ValueError('hour must be in 0..23', hour)
***************
*** 567,570 ****
--- 800,804 ----
          if not -1439 <= tzoffset <= 1439:
              raise ValueError('tzoffset must be in -1439..1439', tzoffset)
+         # XXX This duplicates __year, __month, __day for convenience :-(
          self.__year = year
          self.__month = month
***************
*** 608,621 ****
      utcnow = classmethod(utcnow)
  
-     def fromordinal(cls, n):
-         """Contruct a datetime from a proleptic Gregorian ordinal.
- 
-         January 1 of year 1 is day 1.  Only the year, month and day are
-         non-zero in the result.
-         """
-         y, m, d = _ord2ymd(n)
-         return cls(y, m, d)
-     fromordinal = classmethod(fromordinal)
- 
      # Conversions to string
  
--- 842,845 ----
***************
*** 627,631 ****
              del L[-1]
          s = ", ".join(map(str, L))
!         return "datetime(%s, tzoffset=%d)" % (s, self.__tzoffset)
  
      def __str__(self):
--- 851,857 ----
              del L[-1]
          s = ", ".join(map(str, L))
!         return "%s(%s, tzoffset=%d)" % (self.__class__.__name__,
!                                         s,
!                                         self.__tzoffset)
  
      def __str__(self):
***************
*** 634,641 ****
  
      # Read-only field accessors
-     year = property(lambda self: self.__year,
-                     doc="year (%d-%d)" % (MINYEAR, MAXYEAR))
-     month = property(lambda self: self.__month, doc="month (1-12)")
-     day = property(lambda self: self.__day, doc="day (1-31)")
      hour = property(lambda self: self.__hour, doc="hour (0-23)")
      minute = property(lambda self: self.__minute, doc="minute (0-59)")
--- 860,863 ----
***************
*** 657,676 ****
          return t.time()
  
-     def timetuple(self):
-         "Return local time tuple compatible with time.localtime()."
-         return _time.localtime(self._mktime())
- 
      def utctimetuple(self):
          "Return UTC time tuple compatible with time.gmtime()."
          return _time.gmtime(self._mktime())
  
-     def toordinal(self):
-         """Return proleptic Gregorian ordinal for the year, month and day.
- 
-         January 1 of year 1 is day 1.  Only the year, month and day values
-         contribute to the result.
-         """
-         return _ymd2ord(self.__year, self.__month, self.__day)
- 
      def __cmp__(self, other):
          "Three-way comparison."
--- 879,886 ----
***************
*** 727,738 ****
              t = tmxxx(t.year, t.month, t.day, t.hour,
                        t.minute - tzoffset + tzoffset1, self.__second)
!             tzoffset2 = _localtzoffset(t.year, t.month, t.day, t.hour, t.minute)
              assert tzoffset2 == tzoffset1 # XXX Hah!
          return t.ctime()
  
-     def strftime(self, fmt):
-         "Format using strftime() in local time."
-         return _time.strftime(fmt, _time.localtime(self._mktime()))
- 
      def utcctime(self):
          "Format a la ctime() in UTC."
--- 937,945 ----
              t = tmxxx(t.year, t.month, t.day, t.hour,
                        t.minute - tzoffset + tzoffset1, self.__second)
!             tzoffset2 = _localtzoffset(t.year, t.month, t.day,
!                                        t.hour, t.minute)
              assert tzoffset2 == tzoffset1 # XXX Hah!
          return t.ctime()
  
      def utcctime(self):
          "Format a la ctime() in UTC."
***************
*** 747,755 ****
      # Computations
  
-     def _checkOverflow(self, year):
-         if not MINYEAR <= year <= MAXYEAR:
-             raise OverflowError("datetime +/-: result year %d not in %d..%d" %
-                                 (year, MINYEAR, MAXYEAR))
- 
      def __add__(self, other):
          "Add a datetime to a timedelta."
--- 954,957 ----
***************
*** 772,777 ****
      __radd__ = __add__
  
-     timedelta_class = timedelta # Allows a subclass to override
- 
      def __sub__(self, other):
          """Subtract two datetimes, or a datetime and a timedelta.
--- 974,977 ----
***************
*** 796,836 ****
          return NotImplemented
  
!     # Day-of-the-week and week-of-the-year, according to ISO
! 
!     def weekday(self):
!         "Return day of the week, where Monday == 0 ... Sunday == 6."
!         return (self.toordinal() + 6) % 7
! 
!     def isoweekday(self):
!         "Return day of the week, where Monday == 1 ... Sunday == 7."
!         # 1-Jan-0001 is a Monday
!         return self.toordinal() % 7 or 7
! 
!     def isocalendar(self):
!         """Return a 3-tuple containing ISO year, week number, and weekday.
! 
!         The first ISO week of the year is the (Mon-Sun) week
!         containing the year's first Thursday; everything rest derives
!         from that.
! 
!         The first week is 1; Monday is 1 ... Sunday is 7.
! 
!         ISO calendar algorithm taken from
!         http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
!         """
!         year = self.__year
!         week1monday = _isoweek1monday(year)
!         today = _ymd2ord(self.__year, self.__month, self.__day)
!         # Internally, week and day have origin 0
!         week, day = divmod(today - week1monday, 7)
!         if week < 0:
!             year -= 1
!             week1monday = _isoweek1monday(year)
!             week, day = divmod(today - week1monday, 7)
!         elif week >= 52:
!             if today >= _isoweek1monday(year+1):
!                 year += 1
!                 week = 0
!         return year, week+1, day+1
  
      def isoformat(self, sep='T'):
--- 996,1000 ----
          return NotImplemented
  
!     # ISO formats including time and tzoffset
  
      def isoformat(self, sep='T'):

Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -d -r1.36 -r1.37
*** test_datetime.py	5 Mar 2002 08:53:33 -0000	1.36
--- test_datetime.py	5 Mar 2002 14:14:48 -0000	1.37
***************
*** 7,28 ****
  import unittest
  
! from datetime import datetime, timedelta, MINYEAR, MAXYEAR
  
! class TestDateTime(unittest.TestCase):
  
      def test_basic_attributes(self):
!         dt = datetime(2002, 3, 1, 12, 0, 0)
          self.assertEqual(dt.year, 2002)
          self.assertEqual(dt.month, 3)
          self.assertEqual(dt.day, 1)
-         self.assertEqual(dt.hour, 12)
-         self.assertEqual(dt.minute, 0)
-         self.assertEqual(dt.second, 0)
-         self.assertEqual(dt.microsecond, 0)
  
      def test_roundtrip(self):
!         for dt in (datetime(1, 2, 3, 4, 5, 6, 7, 8),
!                    datetime.now()):
!             # Verify dt -> string -> datetime identity.
              s = repr(dt)
              dt2 = eval(s)
--- 7,91 ----
  import unittest
  
! from datetime import date, datetime, timedelta, MINYEAR, MAXYEAR
  
! 
! class TestTimeDelta(unittest.TestCase):
! 
!     def test_timedelta(self):
!         a = timedelta(7) # One week
!         b = timedelta(0, 60) # One minute
!         c = timedelta(0, 0, 1000) # One millisecond
!         self.assertEqual(a+b+c, timedelta(7, 60, 1000))
!         self.assertEqual(a-b, timedelta(6, 24*3600 - 60))
!         self.assertEqual(-a, timedelta(-7))
!         self.assertEqual(+a, timedelta(7))
!         self.assertEqual(-b, timedelta(-1, 24*3600 - 60))
!         self.assertEqual(-c, timedelta(-1, 24*3600 - 1, 999000))
!         self.assertEqual(abs(a), a)
!         self.assertEqual(abs(-a), a)
!         self.assertEqual(timedelta(6, 24*3600), a)
!         self.assertEqual(timedelta(0, 0, 60*1000000), b)
!         self.assertEqual(a*10, timedelta(70))
!         self.assertEqual(a*10, 10*a)
!         self.assertEqual(a*10L, 10*a)
!         self.assertEqual(b*10, timedelta(0, 600))
!         self.assertEqual(10*b, timedelta(0, 600))
!         self.assertEqual(b*10L, timedelta(0, 600))
!         self.assertEqual(c*10, timedelta(0, 0, 10000))
!         self.assertEqual(10*c, timedelta(0, 0, 10000))
!         self.assertEqual(c*10L, timedelta(0, 0, 10000))
!         self.assertEqual(a*-1, -a)
!         self.assertEqual(b*-2, -b-b)
!         self.assertEqual(c*-2, -c+-c)
!         self.assertEqual(b*(60*24), (b*60)*24)
!         self.assertEqual(b*(60*24), (60*b)*24)
!         self.assertEqual(c*1000, timedelta(0, 1))
!         self.assertEqual(1000*c, timedelta(0, 1))
!         self.assertEqual(a//7, timedelta(1))
!         self.assertEqual(b//10, timedelta(0, 6))
!         self.assertEqual(c//1000, timedelta(0, 0, 1))
!         self.assertEqual(a//10, timedelta(0, 7*24*360))
!         self.assertEqual(a//3600000, timedelta(0, 0, 7*24*1000))
!         # Add/sub ints, longs, floats should be illegal
!         for i in 1, 1L, 1.0:
!             self.assertRaises(TypeError, lambda: a+i)
!             self.assertRaises(TypeError, lambda: a-i)
!             self.assertRaises(TypeError, lambda: i+a)
!             self.assertRaises(TypeError, lambda: i-a)
!         # Check keyword args to constructor
!         eq = self.assertEqual
!         td = timedelta
!         eq(td(1), td(days=1))
!         eq(td(0, 1), td(seconds=1))
!         eq(td(0, 0, 1), td(microseconds=1))
!         eq(td(weeks=1), td(days=7))
!         eq(td(days=1), td(hours=24))
!         eq(td(hours=1), td(minutes=60))
!         eq(td(minutes=1), td(seconds=60))
!         eq(td(seconds=1), td(milliseconds=1000))
!         eq(td(milliseconds=1), td(microseconds=1000))
!         # Check float args to constructor
!         eq(td(weeks=1.0/7), td(days=1))
!         eq(td(days=1.0/24), td(hours=1))
!         eq(td(hours=1.0/60), td(minutes=1))
!         eq(td(minutes=1.0/60), td(seconds=1))
!         eq(td(seconds=0.001), td(milliseconds=1))
!         eq(td(milliseconds=0.001), td(microseconds=1))
! 
! 
! class TestDate(unittest.TestCase):
! 
!     theclass = date
  
      def test_basic_attributes(self):
!         dt = self.theclass(2002, 3, 1)
          self.assertEqual(dt.year, 2002)
          self.assertEqual(dt.month, 3)
          self.assertEqual(dt.day, 1)
  
      def test_roundtrip(self):
!         for dt in (self.theclass(1, 2, 3),
!                    self.theclass.today()):
!             # Verify dt -> string -> date identity.
              s = repr(dt)
              dt2 = eval(s)
***************
*** 30,64 ****
  
              # Verify identity via reconstructing from pieces.
!             dt2 = datetime(dt.year, dt.month, dt.day,
!                            dt.hour, dt.minute, dt.second,
!                            dt.microsecond, dt.tzoffset)
              self.assertEqual(dt, dt2)
  
-     def test_tz_independent_comparing(self):
-         dt1 = datetime(2002, 3, 1, 9, 0, 0, tzoffset=-60)
-         dt2 = datetime(2002, 3, 1, 10, 0, 0, tzoffset=-60)
-         dt3 = datetime(2002, 3, 1, 10, 0, 0, tzoffset=0)
-         self.assertEqual(dt1, dt3)
-         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(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(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60)
-         dt2 = datetime(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0)
-         self.assertEqual(dt1, dt2)
-         dt2 += us
-         self.assertEqual(dt2 - dt1, us)
-         self.assert_(dt1 < dt2)
- 
      def test_ordinal_conversions(self):
          from datetime import _ymd2ord, _ord2ymd
--- 93,99 ----
  
              # Verify identity via reconstructing from pieces.
!             dt2 = self.theclass(dt.year, dt.month, dt.day)
              self.assertEqual(dt, dt2)
  
      def test_ordinal_conversions(self):
          from datetime import _ymd2ord, _ord2ymd
***************
*** 98,151 ****
      def test_bad_constructor_arguments(self):
          # bad years
!         datetime(MINYEAR, 1, 1)  # no exception
!         datetime(MAXYEAR, 1, 1)  # no exception
!         self.assertRaises(ValueError, datetime, MINYEAR-1, 1, 1)
!         self.assertRaises(ValueError, datetime, MAXYEAR+1, 1, 1)
          # bad months
!         datetime(2000, 1, 1)    # no exception
!         datetime(2000, 12, 1)   # no exception
!         self.assertRaises(ValueError, datetime, 2000, 0, 1)
!         self.assertRaises(ValueError, datetime, 2000, 13, 1)
          # bad days
!         datetime(2000, 2, 29)   # no exception
!         datetime(2004, 2, 29)   # no exception
!         datetime(2400, 2, 29)   # no exception
!         self.assertRaises(ValueError, datetime, 2000, 2, 30)
!         self.assertRaises(ValueError, datetime, 2001, 2, 29)
!         self.assertRaises(ValueError, datetime, 2100, 2, 29)
!         self.assertRaises(ValueError, datetime, 1900, 2, 29)
!         self.assertRaises(ValueError, datetime, 2000, 1, 0)
!         self.assertRaises(ValueError, datetime, 2000, 1, 32)
!         # bad hours
!         datetime(2000, 1, 31, 0)    # no exception
!         datetime(2000, 1, 31, 23)   # no exception
!         self.assertRaises(ValueError, datetime, 2000, 1, 31, -1)
!         self.assertRaises(ValueError, datetime, 2000, 1, 31, 24)
!         # bad minutes
!         datetime(2000, 1, 31, 23, 0)    # no exception
!         datetime(2000, 1, 31, 23, 59)   # no exception
!         self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, -1)
!         self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 60)
!         # bad seconds
!         datetime(2000, 1, 31, 23, 59, 0)    # no exception
!         datetime(2000, 1, 31, 23, 59, 59)   # no exception
!         self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, -1)
!         self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 60)
!         # bad microseconds
!         datetime(2000, 1, 31, 23, 59, 59, 0)    # no exception
!         datetime(2000, 1, 31, 23, 59, 59, 999999)   # no exception
!         self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 59, -1)
!         self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 59,
!                           1000000)
!         # bad tzoffet
!         datetime(2, 1, 1, 0, 0, 0, 0, -1439)    # no exception
!         datetime(2, 1, 1, 0, 0, 0, 0,  1439)   # no exception
!         self.assertRaises(ValueError, datetime, 2, 1, 1, 0, 0, 0, 0, -1440)
!         self.assertRaises(ValueError, datetime, 2, 1, 1, 0, 0, 0, 0,  1440)
  
      def test_hash_equality(self):
!         d = datetime(2000, 12, 31, 23, 30, 17, tzoffset=-35)
!         # same thing in UTC.
!         e = datetime(2001,  1,  1,  0,  5, 17, tzoffset=0)
          self.assertEqual(d, e)
          self.assertEqual(hash(d), hash(e))
--- 133,160 ----
      def test_bad_constructor_arguments(self):
          # bad years
!         self.theclass(MINYEAR, 1, 1)  # no exception
!         self.theclass(MAXYEAR, 1, 1)  # no exception
!         self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1)
!         self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1)
          # bad months
!         self.theclass(2000, 1, 1)    # no exception
!         self.theclass(2000, 12, 1)   # no exception
!         self.assertRaises(ValueError, self.theclass, 2000, 0, 1)
!         self.assertRaises(ValueError, self.theclass, 2000, 13, 1)
          # bad days
!         self.theclass(2000, 2, 29)   # no exception
!         self.theclass(2004, 2, 29)   # no exception
!         self.theclass(2400, 2, 29)   # no exception
!         self.assertRaises(ValueError, self.theclass, 2000, 2, 30)
!         self.assertRaises(ValueError, self.theclass, 2001, 2, 29)
!         self.assertRaises(ValueError, self.theclass, 2100, 2, 29)
!         self.assertRaises(ValueError, self.theclass, 1900, 2, 29)
!         self.assertRaises(ValueError, self.theclass, 2000, 1, 0)
!         self.assertRaises(ValueError, self.theclass, 2000, 1, 32)
  
      def test_hash_equality(self):
!         d = self.theclass(2000, 12, 31)
!         # same thing
!         e = self.theclass(2000, 12, 31)
          self.assertEqual(d, e)
          self.assertEqual(hash(d), hash(e))
***************
*** 157,163 ****
          self.assertEqual(dic[e], 2)
  
!         d = datetime(2001,  1,  1,  0,  5, 17, tzoffset=35)
!         # same thing in UTC.
!         e = datetime(2000, 12, 31, 23, 30, 17, tzoffset=0)
          self.assertEqual(d, e)
          self.assertEqual(hash(d), hash(e))
--- 166,172 ----
          self.assertEqual(dic[e], 2)
  
!         d = self.theclass(2001,  1,  1)
!         # same thing
!         e = self.theclass(2001,  1,  1)
          self.assertEqual(d, e)
          self.assertEqual(hash(d), hash(e))
***************
*** 169,280 ****
          self.assertEqual(dic[e], 2)
  
-     def test_timedelta(self):
-         a = timedelta(7) # One week
-         b = timedelta(0, 60) # One minute
-         c = timedelta(0, 0, 1000) # One millisecond
-         self.assertEqual(a+b+c, timedelta(7, 60, 1000))
-         self.assertEqual(a-b, timedelta(6, 24*3600 - 60))
-         self.assertEqual(-a, timedelta(-7))
-         self.assertEqual(+a, timedelta(7))
-         self.assertEqual(-b, timedelta(-1, 24*3600 - 60))
-         self.assertEqual(-c, timedelta(-1, 24*3600 - 1, 999000))
-         self.assertEqual(abs(a), a)
-         self.assertEqual(abs(-a), a)
-         self.assertEqual(timedelta(6, 24*3600), a)
-         self.assertEqual(timedelta(0, 0, 60*1000000), b)
-         self.assertEqual(a*10, timedelta(70))
-         self.assertEqual(a*10, 10*a)
-         self.assertEqual(a*10L, 10*a)
-         self.assertEqual(b*10, timedelta(0, 600))
-         self.assertEqual(10*b, timedelta(0, 600))
-         self.assertEqual(b*10L, timedelta(0, 600))
-         self.assertEqual(c*10, timedelta(0, 0, 10000))
-         self.assertEqual(10*c, timedelta(0, 0, 10000))
-         self.assertEqual(c*10L, timedelta(0, 0, 10000))
-         self.assertEqual(a*-1, -a)
-         self.assertEqual(b*-2, -b-b)
-         self.assertEqual(c*-2, -c+-c)
-         self.assertEqual(b*(60*24), (b*60)*24)
-         self.assertEqual(b*(60*24), (60*b)*24)
-         self.assertEqual(c*1000, timedelta(0, 1))
-         self.assertEqual(1000*c, timedelta(0, 1))
-         self.assertEqual(a//7, timedelta(1))
-         self.assertEqual(b//10, timedelta(0, 6))
-         self.assertEqual(c//1000, timedelta(0, 0, 1))
-         self.assertEqual(a//10, timedelta(0, 7*24*360))
-         self.assertEqual(a//3600000, timedelta(0, 0, 7*24*1000))
-         # Add/sub ints, longs, floats should be illegal
-         for i in 1, 1L, 1.0:
-             self.assertRaises(TypeError, lambda: a+i)
-             self.assertRaises(TypeError, lambda: a-i)
-             self.assertRaises(TypeError, lambda: i+a)
-             self.assertRaises(TypeError, lambda: i-a)
-         # Check keyword args to constructor
-         eq = self.assertEqual
-         td = timedelta
-         eq(td(1), td(days=1))
-         eq(td(0, 1), td(seconds=1))
-         eq(td(0, 0, 1), td(microseconds=1))
-         eq(td(weeks=1), td(days=7))
-         eq(td(days=1), td(hours=24))
-         eq(td(hours=1), td(minutes=60))
-         eq(td(minutes=1), td(seconds=60))
-         eq(td(seconds=1), td(milliseconds=1000))
-         eq(td(milliseconds=1), td(microseconds=1000))
-         # Check float args to constructor
-         eq(td(weeks=1.0/7), td(days=1))
-         eq(td(days=1.0/24), td(hours=1))
-         eq(td(hours=1.0/60), td(minutes=1))
-         eq(td(minutes=1.0/60), td(seconds=1))
-         eq(td(seconds=0.001), td(milliseconds=1))
-         eq(td(milliseconds=0.001), td(microseconds=1))
- 
      def test_computations(self):
!         a = datetime(2002, 1, 31)
!         b = datetime(1956, 1, 31)
          diff = a-b
          self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4)))
          self.assertEqual(diff.seconds, 0)
          self.assertEqual(diff.microseconds, 0)
-         a = datetime(2002, 3, 2, 17, 6)
-         millisec = timedelta(0, 0, 1000)
-         hour = timedelta(0, 3600)
          day = timedelta(1)
          week = timedelta(7)
!         self.assertEqual(a + hour, datetime(2002, 3, 2, 18, 6))
!         self.assertEqual(a + 10*hour, datetime(2002, 3, 3, 3, 6))
!         self.assertEqual(a - hour, datetime(2002, 3, 2, 16, 6))
!         self.assertEqual(a - hour, a + -hour)
!         self.assertEqual(a - 20*hour, datetime(2002, 3, 1, 21, 6))
!         self.assertEqual(a + day, datetime(2002, 3, 3, 17, 6))
!         self.assertEqual(a - day, datetime(2002, 3, 1, 17, 6))
!         self.assertEqual(a + week, datetime(2002, 3, 9, 17, 6))
!         self.assertEqual(a - week, datetime(2002, 2, 23, 17, 6))
!         self.assertEqual(a + 52*week, datetime(2003, 3, 1, 17, 6))
!         self.assertEqual(a - 52*week, datetime(2001, 3, 3, 17, 6))
          self.assertEqual((a + week) - a, week)
          self.assertEqual((a + day) - a, day)
-         self.assertEqual((a + hour) - a, hour)
-         self.assertEqual((a + millisec) - a, millisec)
          self.assertEqual((a - week) - a, -week)
          self.assertEqual((a - day) - a, -day)
-         self.assertEqual((a - hour) - a, -hour)
-         self.assertEqual((a - millisec) - a, -millisec)
          self.assertEqual(a - (a + week), -week)
          self.assertEqual(a - (a + day), -day)
-         self.assertEqual(a - (a + hour), -hour)
-         self.assertEqual(a - (a + millisec), -millisec)
          self.assertEqual(a - (a - week), week)
          self.assertEqual(a - (a - day), day)
-         self.assertEqual(a - (a - hour), hour)
-         self.assertEqual(a - (a - millisec), millisec)
-         self.assertEqual(a + (week + day + hour + millisec),
-                          datetime(2002, 3, 10, 18, 6, 0, 1000))
-         self.assertEqual(a + (week + day + hour + millisec),
-                          (((a + week) + day) + hour) + millisec)
-         self.assertEqual(a - (week + day + hour + millisec),
-                          datetime(2002, 2, 22, 16, 5, 59, 999000))
-         self.assertEqual(a - (week + day + hour + millisec),
-                          (((a - week) - day) - hour) - millisec)
          # Add/sub ints, longs, floats should be illegal
          for i in 1, 1L, 1.0:
--- 178,205 ----
          self.assertEqual(dic[e], 2)
  
      def test_computations(self):
!         a = self.theclass(2002, 1, 31)
!         b = self.theclass(1956, 1, 31)
          diff = a-b
          self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4)))
          self.assertEqual(diff.seconds, 0)
          self.assertEqual(diff.microseconds, 0)
          day = timedelta(1)
          week = timedelta(7)
!         a = self.theclass(2002, 3, 2)
!         self.assertEqual(a + day, self.theclass(2002, 3, 3))
!         self.assertEqual(a - day, self.theclass(2002, 3, 1))
!         self.assertEqual(a + week, self.theclass(2002, 3, 9))
!         self.assertEqual(a - week, self.theclass(2002, 2, 23))
!         self.assertEqual(a + 52*week, self.theclass(2003, 3, 1))
!         self.assertEqual(a - 52*week, self.theclass(2001, 3, 3))
          self.assertEqual((a + week) - a, week)
          self.assertEqual((a + day) - a, day)
          self.assertEqual((a - week) - a, -week)
          self.assertEqual((a - day) - a, -day)
          self.assertEqual(a - (a + week), -week)
          self.assertEqual(a - (a + day), -day)
          self.assertEqual(a - (a - week), week)
          self.assertEqual(a - (a - day), day)
          # Add/sub ints, longs, floats should be illegal
          for i in 1, 1L, 1.0:
***************
*** 285,296 ****
  
      def test_overflow(self):
!         tiny = datetime.resolution
  
!         dt = datetime.min + tiny
          dt -= tiny  # no problem
          self.assertRaises(OverflowError, dt.__sub__, tiny)
          self.assertRaises(OverflowError, dt.__add__, -tiny)
  
!         dt = datetime.max - tiny
          dt += tiny  # no problem
          self.assertRaises(OverflowError, dt.__add__, tiny)
--- 210,221 ----
  
      def test_overflow(self):
!         tiny = self.theclass.resolution
  
!         dt = self.theclass.min + tiny
          dt -= tiny  # no problem
          self.assertRaises(OverflowError, dt.__sub__, tiny)
          self.assertRaises(OverflowError, dt.__add__, -tiny)
  
!         dt = self.theclass.max - tiny
          dt += tiny  # no problem
          self.assertRaises(OverflowError, dt.__add__, tiny)
***************
*** 300,308 ****
          for i in range(7):
              # March 4, 2002 is a Monday
!             self.assertEqual(datetime(2002, 3, 4+i).weekday(), i)
!             self.assertEqual(datetime(2002, 3, 4+i).isoweekday(), i+1)
              # January 2, 1956 is a Monday
!             self.assertEqual(datetime(1956, 1, 2+i).weekday(), i)
!             self.assertEqual(datetime(1956, 1, 2+i).isoweekday(), i+1)
  
      def test_isocalendar(self):
--- 225,233 ----
          for i in range(7):
              # March 4, 2002 is a Monday
!             self.assertEqual(self.theclass(2002, 3, 4+i).weekday(), i)
!             self.assertEqual(self.theclass(2002, 3, 4+i).isoweekday(), i+1)
              # January 2, 1956 is a Monday
!             self.assertEqual(self.theclass(1956, 1, 2+i).weekday(), i)
!             self.assertEqual(self.theclass(1956, 1, 2+i).isoweekday(), i+1)
  
      def test_isocalendar(self):
***************
*** 310,324 ****
          # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
          for i in range(7):
!             d = datetime(2003, 12, 22+i)
              self.assertEqual(d.isocalendar(), (2003, 52, i+1))
!             d = datetime(2003, 12, 29) + timedelta(i)
              self.assertEqual(d.isocalendar(), (2004, 1, i+1))
!             d = datetime(2004, 1, 5+i)
              self.assertEqual(d.isocalendar(), (2004, 2, i+1))
!             d = datetime(2009, 12, 21+i)
              self.assertEqual(d.isocalendar(), (2009, 52, i+1))
!             d = datetime(2009, 12, 28) + timedelta(i)
              self.assertEqual(d.isocalendar(), (2009, 53, i+1))
!             d = datetime(2010, 1, 4+i)
              self.assertEqual(d.isocalendar(), (2010, 1, i+1))
  
--- 235,249 ----
          # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
          for i in range(7):
!             d = self.theclass(2003, 12, 22+i)
              self.assertEqual(d.isocalendar(), (2003, 52, i+1))
!             d = self.theclass(2003, 12, 29) + timedelta(i)
              self.assertEqual(d.isocalendar(), (2004, 1, i+1))
!             d = self.theclass(2004, 1, 5+i)
              self.assertEqual(d.isocalendar(), (2004, 2, i+1))
!             d = self.theclass(2009, 12, 21+i)
              self.assertEqual(d.isocalendar(), (2009, 52, i+1))
!             d = self.theclass(2009, 12, 28) + timedelta(i)
              self.assertEqual(d.isocalendar(), (2009, 53, i+1))
!             d = self.theclass(2010, 1, 4+i)
              self.assertEqual(d.isocalendar(), (2010, 1, i+1))
  
***************
*** 355,360 ****
          L = []
          for i in range(400):
!             d = datetime(2000+i, 12, 31)
!             d1 = datetime(1600+i, 12, 31)
              self.assertEqual(d.isocalendar()[1:], d1.isocalendar()[1:])
              if d.isocalendar()[1] == 53:
--- 280,285 ----
          L = []
          for i in range(400):
!             d = self.theclass(2000+i, 12, 31)
!             d1 = self.theclass(1600+i, 12, 31)
              self.assertEqual(d.isocalendar()[1:], d1.isocalendar()[1:])
              if d.isocalendar()[1] == 53:
***************
*** 363,367 ****
  
      def test_isoformat(self):
!         t = datetime(2, 3, 2, 4, 5, 1, 123, tzoffset=-120)
          self.assertEqual(t.isoformat(),    "0002-03-02T04:05:01.000123-02:00")
          self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123-02:00")
--- 288,502 ----
  
      def test_isoformat(self):
!         t = self.theclass(2, 3, 2)
!         self.assertEqual(t.isoformat(), "0002-03-02")
! 
!     def test_ctime(self):
!         t = self.theclass(2002, 3, 2)
!         self.assertEqual(t.ctime(), "Sat Mar  2 00:00:00 2002")
! 
!     def test_resolution_info(self):
!         self.assert_(isinstance(self.theclass.min, self.theclass))
!         self.assert_(isinstance(self.theclass.max, self.theclass))
!         self.assert_(isinstance(self.theclass.resolution, timedelta))
!         self.assert_(self.theclass.max > self.theclass.min)
! 
!     def test_extreme_timedelta(self):
!         big = self.theclass.max - self.theclass.min
!         # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds
!         n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds
!         # n = 315537897599999999 ~= 2**58.13
!         justasbig = timedelta(0, 0, n)
!         self.assertEqual(big, justasbig)
!         self.assertEqual(self.theclass.min + big, self.theclass.max)
!         self.assertEqual(self.theclass.max - big, self.theclass.min)
! 
! 
! class TestDateTime(TestDate):
! 
!     theclass = datetime
! 
!     def test_basic_attributes(self):
!         dt = self.theclass(2002, 3, 1, 12, 0, 0)
!         self.assertEqual(dt.year, 2002)
!         self.assertEqual(dt.month, 3)
!         self.assertEqual(dt.day, 1)
!         self.assertEqual(dt.hour, 12)
!         self.assertEqual(dt.minute, 0)
!         self.assertEqual(dt.second, 0)
!         self.assertEqual(dt.microsecond, 0)
! 
!     def test_roundtrip(self):
!         for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7, 8),
!                    self.theclass.now()):
!             # Verify dt -> string -> datetime identity.
!             s = repr(dt)
!             dt2 = eval(s)
!             self.assertEqual(dt, dt2)
! 
!             # Verify identity via reconstructing from pieces.
!             dt2 = self.theclass(dt.year, dt.month, dt.day,
!                                 dt.hour, dt.minute, dt.second,
!                                 dt.microsecond, dt.tzoffset)
!             self.assertEqual(dt, dt2)
! 
!     def test_tz_independent_comparing(self):
!         dt1 = self.theclass(2002, 3, 1, 9, 0, 0, tzoffset=-60)
!         dt2 = self.theclass(2002, 3, 1, 10, 0, 0, tzoffset=-60)
!         dt3 = self.theclass(2002, 3, 1, 10, 0, 0, tzoffset=0)
!         self.assertEqual(dt1, dt3)
!         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 = self.theclass(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 = self.theclass(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60)
!         dt2 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0)
!         self.assertEqual(dt1, dt2)
!         dt2 += us
!         self.assertEqual(dt2 - dt1, us)
!         self.assert_(dt1 < dt2)
! 
!     def test_bad_constructor_arguments(self):
!         # bad years
!         self.theclass(MINYEAR, 1, 1)  # no exception
!         self.theclass(MAXYEAR, 1, 1)  # no exception
!         self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1)
!         self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1)
!         # bad months
!         self.theclass(2000, 1, 1)    # no exception
!         self.theclass(2000, 12, 1)   # no exception
!         self.assertRaises(ValueError, self.theclass, 2000, 0, 1)
!         self.assertRaises(ValueError, self.theclass, 2000, 13, 1)
!         # bad days
!         self.theclass(2000, 2, 29)   # no exception
!         self.theclass(2004, 2, 29)   # no exception
!         self.theclass(2400, 2, 29)   # no exception
!         self.assertRaises(ValueError, self.theclass, 2000, 2, 30)
!         self.assertRaises(ValueError, self.theclass, 2001, 2, 29)
!         self.assertRaises(ValueError, self.theclass, 2100, 2, 29)
!         self.assertRaises(ValueError, self.theclass, 1900, 2, 29)
!         self.assertRaises(ValueError, self.theclass, 2000, 1, 0)
!         self.assertRaises(ValueError, self.theclass, 2000, 1, 32)
!         # bad hours
!         self.theclass(2000, 1, 31, 0)    # no exception
!         self.theclass(2000, 1, 31, 23)   # no exception
!         self.assertRaises(ValueError, self.theclass, 2000, 1, 31, -1)
!         self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 24)
!         # bad minutes
!         self.theclass(2000, 1, 31, 23, 0)    # no exception
!         self.theclass(2000, 1, 31, 23, 59)   # no exception
!         self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, -1)
!         self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 60)
!         # bad seconds
!         self.theclass(2000, 1, 31, 23, 59, 0)    # no exception
!         self.theclass(2000, 1, 31, 23, 59, 59)   # no exception
!         self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, -1)
!         self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, 60)
!         # bad microseconds
!         self.theclass(2000, 1, 31, 23, 59, 59, 0)    # no exception
!         self.theclass(2000, 1, 31, 23, 59, 59, 999999)   # no exception
!         self.assertRaises(ValueError, self.theclass,
!                           2000, 1, 31, 23, 59, 59, -1)
!         self.assertRaises(ValueError, self.theclass,
!                           2000, 1, 31, 23, 59, 59,
!                           1000000)
!         # bad tzoffet
!         self.theclass(2, 1, 1, 0, 0, 0, 0, -1439)    # no exception
!         self.theclass(2, 1, 1, 0, 0, 0, 0,  1439)   # no exception
!         self.assertRaises(ValueError, self.theclass,
!                           2, 1, 1, 0, 0, 0, 0, -1440)
!         self.assertRaises(ValueError, self.theclass,
!                           2, 1, 1, 0, 0, 0, 0,  1440)
! 
!     def test_hash_equality(self):
!         d = self.theclass(2000, 12, 31, 23, 30, 17, tzoffset=-35)
!         # same thing in UTC.
!         e = self.theclass(2001,  1,  1,  0,  5, 17, tzoffset=0)
!         self.assertEqual(d, e)
!         self.assertEqual(hash(d), hash(e))
! 
!         dic = {d: 1}
!         dic[e] = 2
!         self.assertEqual(len(dic), 1)
!         self.assertEqual(dic[d], 2)
!         self.assertEqual(dic[e], 2)
! 
!         d = self.theclass(2001,  1,  1,  0,  5, 17, tzoffset=35)
!         # same thing in UTC.
!         e = self.theclass(2000, 12, 31, 23, 30, 17, tzoffset=0)
!         self.assertEqual(d, e)
!         self.assertEqual(hash(d), hash(e))
! 
!         dic = {d: 1}
!         dic[e] = 2
!         self.assertEqual(len(dic), 1)
!         self.assertEqual(dic[d], 2)
!         self.assertEqual(dic[e], 2)
! 
!     def test_computations(self):
!         a = self.theclass(2002, 1, 31)
!         b = self.theclass(1956, 1, 31)
!         diff = a-b
!         self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4)))
!         self.assertEqual(diff.seconds, 0)
!         self.assertEqual(diff.microseconds, 0)
!         a = self.theclass(2002, 3, 2, 17, 6)
!         millisec = timedelta(0, 0, 1000)
!         hour = timedelta(0, 3600)
!         day = timedelta(1)
!         week = timedelta(7)
!         self.assertEqual(a + hour, self.theclass(2002, 3, 2, 18, 6))
!         self.assertEqual(a + 10*hour, self.theclass(2002, 3, 3, 3, 6))
!         self.assertEqual(a - hour, self.theclass(2002, 3, 2, 16, 6))
!         self.assertEqual(a - hour, a + -hour)
!         self.assertEqual(a - 20*hour, self.theclass(2002, 3, 1, 21, 6))
!         self.assertEqual(a + day, self.theclass(2002, 3, 3, 17, 6))
!         self.assertEqual(a - day, self.theclass(2002, 3, 1, 17, 6))
!         self.assertEqual(a + week, self.theclass(2002, 3, 9, 17, 6))
!         self.assertEqual(a - week, self.theclass(2002, 2, 23, 17, 6))
!         self.assertEqual(a + 52*week, self.theclass(2003, 3, 1, 17, 6))
!         self.assertEqual(a - 52*week, self.theclass(2001, 3, 3, 17, 6))
!         self.assertEqual((a + week) - a, week)
!         self.assertEqual((a + day) - a, day)
!         self.assertEqual((a + hour) - a, hour)
!         self.assertEqual((a + millisec) - a, millisec)
!         self.assertEqual((a - week) - a, -week)
!         self.assertEqual((a - day) - a, -day)
!         self.assertEqual((a - hour) - a, -hour)
!         self.assertEqual((a - millisec) - a, -millisec)
!         self.assertEqual(a - (a + week), -week)
!         self.assertEqual(a - (a + day), -day)
!         self.assertEqual(a - (a + hour), -hour)
!         self.assertEqual(a - (a + millisec), -millisec)
!         self.assertEqual(a - (a - week), week)
!         self.assertEqual(a - (a - day), day)
!         self.assertEqual(a - (a - hour), hour)
!         self.assertEqual(a - (a - millisec), millisec)
!         self.assertEqual(a + (week + day + hour + millisec),
!                          self.theclass(2002, 3, 10, 18, 6, 0, 1000))
!         self.assertEqual(a + (week + day + hour + millisec),
!                          (((a + week) + day) + hour) + millisec)
!         self.assertEqual(a - (week + day + hour + millisec),
!                          self.theclass(2002, 2, 22, 16, 5, 59, 999000))
!         self.assertEqual(a - (week + day + hour + millisec),
!                          (((a - week) - day) - hour) - millisec)
!         # Add/sub ints, longs, floats should be illegal
!         for i in 1, 1L, 1.0:
!             self.assertRaises(TypeError, lambda: a+i)
!             self.assertRaises(TypeError, lambda: a-i)
!             self.assertRaises(TypeError, lambda: i+a)
!             self.assertRaises(TypeError, lambda: i-a)
! 
!     def test_isoformat(self):
!         t = self.theclass(2, 3, 2, 4, 5, 1, 123, tzoffset=-120)
          self.assertEqual(t.isoformat(),    "0002-03-02T04:05:01.000123-02:00")
          self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123-02:00")
***************
*** 372,376 ****
          from datetime import tmxxx
          for timestamp in 123456789.0, 987654321.0:
!             dt = datetime.utcfromtimestamp(timestamp)
              # Mangles the fields, but in such a way that normalization should
              # restore them to dt's values.
--- 507,511 ----
          from datetime import tmxxx
          for timestamp in 123456789.0, 987654321.0:
!             dt = self.theclass.utcfromtimestamp(timestamp)
              # Mangles the fields, but in such a way that normalization should
              # restore them to dt's values.
***************
*** 378,388 ****
                         dt.hour - 24*100, dt.minute - 3, dt.second + 12,
                         (3*60 - 12) * 1000000)
!             dt2 = datetime(tm.year, tm.month, tm.day, tm.hour, tm.minute,
!                            tm.second, tm.microsecond, tzoffset=0)
              self.assertEqual(dt, dt2)
              self.assertEqual(timestamp, tm.time())
  
      def test_ctime(self):
!         t = datetime(2002, 3, 2, 18, 3, 5, 123)
          self.assertEqual(t.ctime(), "Sat Mar  2 18:03:05 2002")
          # XXX Can only test utcctime() in known timezone :-(
--- 513,523 ----
                         dt.hour - 24*100, dt.minute - 3, dt.second + 12,
                         (3*60 - 12) * 1000000)
!             dt2 = self.theclass(tm.year, tm.month, tm.day, tm.hour, tm.minute,
!                                 tm.second, tm.microsecond, tzoffset=0)
              self.assertEqual(dt, dt2)
              self.assertEqual(timestamp, tm.time())
  
      def test_ctime(self):
!         t = self.theclass(2002, 3, 2, 18, 3, 5, 123)
          self.assertEqual(t.ctime(), "Sat Mar  2 18:03:05 2002")
          # XXX Can only test utcctime() in known timezone :-(
***************
*** 398,420 ****
              self.fail("Can't test utcctime()")
  
-     def test_resolution_info(self):
-         self.assert_(isinstance(datetime.min, datetime))
-         self.assert_(isinstance(datetime.max, datetime))
-         self.assert_(isinstance(datetime.resolution, timedelta))
-         self.assert_(datetime.max > datetime.min)
- 
-     def test_extreme_timedelta(self):
-         big = datetime.max - datetime.min
-         # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds
-         n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds
-         # n = 315537897599999999 ~= 2**58.13
-         justasbig = timedelta(0, 0, n)
-         self.assertEqual(big, justasbig)
-         self.assertEqual(datetime.min + big, datetime.max)
-         self.assertEqual(datetime.max - big, datetime.min)
  
  def test_suite():
!     s1 = unittest.makeSuite(TestDateTime, 'test')
!     return unittest.TestSuite([s1])
  
  def test_main():
--- 533,542 ----
              self.fail("Can't test utcctime()")
  
  
  def test_suite():
!     s1 = unittest.makeSuite(TestTimeDelta, 'test')
!     s2 = unittest.makeSuite(TestDate, 'test')
!     s3 = unittest.makeSuite(TestDateTime, 'test')
!     return unittest.TestSuite([s1, s2, s3])
  
  def test_main():