[Python-checkins] python/dist/src/Lib/test test_datetime.py,1.10,1.11

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Wed, 25 Dec 2002 21:01:21 -0800


Update of /cvsroot/python/python/dist/src/Lib/test
In directory sc8-pr-cvs1:/tmp/cvs-serv4169/python/Lib/test

Modified Files:
	test_datetime.py 
Log Message:
Added tests to ensure that timetz comparison, and datetimetz
subtraction, work as documented.  In the Python implementation,
they weren't calling utcoffset() if both operands had the same
tzinfo object.  That's fine if it so happens that the shared
tzinfo object returns a fixed offset (independent of operand),
but can give wrong results if that's not so, and the latter
obtains in a tzinfo subclass instance trying to model both
standard and daylight times.  The C implementation was already
doing this "correctly", so we're just adding tests to verify it.


Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/test_datetime.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** test_datetime.py	25 Dec 2002 07:40:55 -0000	1.10
--- test_datetime.py	26 Dec 2002 05:01:19 -0000	1.11
***************
*** 1655,1658 ****
--- 1655,1689 ----
          self.assertRaises(ValueError, t.dst)
  
+     def test_aware_compare(self):
+         cls = self.theclass
+ 
+         # Primarily trying to ensure that utcoffset() gets called even if
+         # the comparands have the same tzinfo member.  timetz comparison
+         # didn't used to do so, although datetimetz comparison did.
+         class OperandDependentOffset(tzinfo):
+             def utcoffset(self, t):
+                 if t.minute < 10:
+                     return t.minute # d0 and d1 equal after adjustment
+                 else:
+                     return 59       # d2 off in the weeds
+ 
+         base = cls(8, 9, 10, tzinfo=OperandDependentOffset())
+         d0 = base.replace(minute=3)
+         d1 = base.replace(minute=9)
+         d2 = base.replace(minute=11)
+         for x in d0, d1, d2:
+             for y in d0, d1, d2:
+                 got = cmp(x, y)
+                 if (x is d0 or x is d1) and (y is d0 or y is d1):
+                     expected = 0
+                 elif x is y is d2:
+                     expected = 0
+                 elif x is d2:
+                     expected = -1
+                 else:
+                     assert y is d2
+                     expected = 1
+                 self.assertEqual(got, expected)
+ 
  
  class TestTimeTZ(TestTime, TZInfoBase):
***************
*** 1863,1866 ****
--- 1894,1898 ----
          self.assertRaises(ValueError, base.replace, microsecond=1000000)
  
+ 
  class TestDateTimeTZ(TestDateTime, TZInfoBase):
      theclass = datetimetz
***************
*** 2044,2049 ****
          now = self.theclass.now()
          tz55 = FixedOffset(-330, "west 5:30")
!         timeaware = timetz(now.hour, now.minute, now.second,
!                            now.microsecond, tzinfo=tz55)
          nowaware = self.theclass.combine(now.date(), timeaware)
          self.failUnless(nowaware.tzinfo is tz55)
--- 2076,2080 ----
          now = self.theclass.now()
          tz55 = FixedOffset(-330, "west 5:30")
!         timeaware = now.timetz().replace(tzinfo=tz55)
          nowaware = self.theclass.combine(now.date(), timeaware)
          self.failUnless(nowaware.tzinfo is tz55)
***************
*** 2081,2091 ****
          # Make up a random timezone.
          tzr = FixedOffset(random.randrange(-1439, 1440), "randomtimezone")
!         # Attach it to nowawareplus -- this is clumsy.
!         nowawareplus = self.theclass.combine(nowawareplus.date(),
!                                              timetz(nowawareplus.hour,
!                                                     nowawareplus.minute,
!                                                     nowawareplus.second,
!                                                     nowawareplus.microsecond,
!                                                     tzinfo=tzr))
          self.failUnless(nowawareplus.tzinfo is tzr)
          # Make sure the difference takes the timezone adjustments into account.
--- 2112,2117 ----
          # Make up a random timezone.
          tzr = FixedOffset(random.randrange(-1439, 1440), "randomtimezone")
!         # Attach it to nowawareplus.
!         nowawareplus = nowawareplus.replace(tzinfo=tzr)
          self.failUnless(nowawareplus.tzinfo is tzr)
          # Make sure the difference takes the timezone adjustments into account.
***************
*** 2360,2363 ****
--- 2386,2421 ----
          self.failUnless(got.tzinfo is expected.tzinfo)
          self.assertEqual(got, expected)
+ 
+     def test_aware_subtract(self):
+         cls = self.theclass
+ 
+         # Primarily trying to ensure that utcoffset() gets called even if
+         # the operands have the same tzinfo member.  Subtraction didn't
+         # used to do this, and it makes a difference for DST-aware tzinfo
+         # instances.
+         class OperandDependentOffset(tzinfo):
+             def utcoffset(self, t):
+                 if t.minute < 10:
+                     return t.minute # d0 and d1 equal after adjustment
+                 else:
+                     return 59       # d2 off in the weeds
+ 
+         base = cls(8, 9, 10, 11, 12, 13, 14, tzinfo=OperandDependentOffset())
+         d0 = base.replace(minute=3)
+         d1 = base.replace(minute=9)
+         d2 = base.replace(minute=11)
+         for x in d0, d1, d2:
+             for y in d0, d1, d2:
+                 got = x - y
+                 if (x is d0 or x is d1) and (y is d0 or y is d1):
+                     expected = timedelta(0)
+                 elif x is y is d2:
+                     expected = timedelta(0)
+                 elif x is d2:
+                     expected = timedelta(minutes=(11-59)-0)
+                 else:
+                     assert y is d2
+                     expected = timedelta(minutes=0-(11-59))
+                 self.assertEqual(got, expected)