10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi"""Test date/time type.
20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSee http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases
40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi"""
50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom __future__ import division
60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport sys
70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport pickle
80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport cPickle
90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport unittest
100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom test import test_support
120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom datetime import MINYEAR, MAXYEAR
140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom datetime import timedelta
150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom datetime import tzinfo
160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom datetime import time
170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom datetime import date, datetime
180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yipickle_choices = [(pickler, unpickler, proto)
200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                  for pickler in pickle, cPickle
210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                  for unpickler in pickle, cPickle
220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                  for proto in range(3)]
230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiassert len(pickle_choices) == 2*2*3
240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# An arbitrary collection of objects of non-datetime types, for testing
260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# mixed-type comparisons.
270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiOTHERSTUFF = (10, 10L, 34.5, "abc", {}, [], ())
280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#############################################################################
310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# module tests
320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestModule(unittest.TestCase):
340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_constants(self):
360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import datetime
370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(datetime.MINYEAR, 1)
380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(datetime.MAXYEAR, 9999)
390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#############################################################################
410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# tzinfo tests
420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass FixedOffset(tzinfo):
440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, offset, name, dstoffset=42):
450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if isinstance(offset, int):
460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            offset = timedelta(minutes=offset)
470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if isinstance(dstoffset, int):
480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dstoffset = timedelta(minutes=dstoffset)
490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.__offset = offset
500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.__name = name
510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.__dstoffset = dstoffset
520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __repr__(self):
530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.__name.lower()
540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def utcoffset(self, dt):
550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.__offset
560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def tzname(self, dt):
570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.__name
580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def dst(self, dt):
590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.__dstoffset
600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass PicklableFixedOffset(FixedOffset):
620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, offset=None, name=None, dstoffset=None):
630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        FixedOffset.__init__(self, offset, name, dstoffset)
640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestTZInfo(unittest.TestCase):
660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_non_abstractness(self):
680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # In order to allow subclasses to get pickled, the C implementation
690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # wasn't able to get away with having __init__ raise
700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # NotImplementedError.
710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        useless = tzinfo()
720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = datetime.max
730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(NotImplementedError, useless.tzname, dt)
740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(NotImplementedError, useless.utcoffset, dt)
750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(NotImplementedError, useless.dst, dt)
760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_subclass_must_override(self):
780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class NotEnough(tzinfo):
790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __init__(self, offset, name):
800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.__offset = offset
810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.__name = name
820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(issubclass(NotEnough, tzinfo))
830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        ne = NotEnough(3, "NotByALongShot")
840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(ne, tzinfo)
850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = datetime.now()
870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(NotImplementedError, ne.tzname, dt)
880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(NotImplementedError, ne.utcoffset, dt)
890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(NotImplementedError, ne.dst, dt)
900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_normal(self):
920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fo = FixedOffset(3, "Three")
930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(fo, tzinfo)
940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for dt in datetime.now(), None:
950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(fo.utcoffset(dt), timedelta(minutes=3))
960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(fo.tzname(dt), "Three")
970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(fo.dst(dt), timedelta(minutes=42))
980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling_base(self):
1000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # There's no point to pickling tzinfo objects on their own (they
1010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # carry no data), but they need to be picklable anyway else
1020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # concrete subclasses can't be pickled.
1030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = tzinfo.__new__(tzinfo)
1040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(type(orig) is tzinfo)
1050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
1060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
1070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
1080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(type(derived) is tzinfo)
1090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling_subclass(self):
1110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Make sure we can pickle/unpickle an instance of a subclass.
1120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        offset = timedelta(minutes=-300)
1130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = PicklableFixedOffset(offset, 'cookie')
1140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(orig, tzinfo)
1150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(type(orig) is PicklableFixedOffset)
1160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(orig.utcoffset(None), offset)
1170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(orig.tzname(None), 'cookie')
1180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
1190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
1200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
1210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertIsInstance(derived, tzinfo)
1220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(type(derived) is PicklableFixedOffset)
1230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(derived.utcoffset(None), offset)
1240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(derived.tzname(None), 'cookie')
1250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#############################################################################
1270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Base clase for testing a particular aspect of timedelta, time, date and
1280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# datetime comparisons.
1290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass HarmlessMixedComparison:
1310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Test that __eq__ and __ne__ don't complain for mixed-type comparisons.
1320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Subclasses must define 'theclass', and theclass(1, 1, 1) must be a
1340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # legit constructor.
1350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_harmless_mixed_comparison(self):
1370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        me = self.theclass(1, 1, 1)
1380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertFalse(me == ())
1400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(me != ())
1410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertFalse(() == me)
1420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(() != me)
1430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIn(me, [1, 20L, [], me])
1450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIn([], [me, 1, 20L, []])
1460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_harmful_mixed_comparison(self):
1480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        me = self.theclass(1, 1, 1)
1490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: me < ())
1510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: me <= ())
1520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: me > ())
1530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: me >= ())
1540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: () < me)
1560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: () <= me)
1570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: () > me)
1580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: () >= me)
1590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, cmp, (), me)
1610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, cmp, me, ())
1620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#############################################################################
1640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# timedelta tests
1650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestTimeDelta(HarmlessMixedComparison, unittest.TestCase):
1670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    theclass = timedelta
1690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_constructor(self):
1710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq = self.assertEqual
1720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td = timedelta
1730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Check keyword args to constructor
1750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(), td(weeks=0, days=0, hours=0, minutes=0, seconds=0,
1760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    milliseconds=0, microseconds=0))
1770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(1), td(days=1))
1780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(0, 1), td(seconds=1))
1790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(0, 0, 1), td(microseconds=1))
1800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(weeks=1), td(days=7))
1810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(days=1), td(hours=24))
1820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(hours=1), td(minutes=60))
1830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(minutes=1), td(seconds=60))
1840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(seconds=1), td(milliseconds=1000))
1850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(milliseconds=1), td(microseconds=1000))
1860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Check float args to constructor
1880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(weeks=1.0/7), td(days=1))
1890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(days=1.0/24), td(hours=1))
1900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(hours=1.0/60), td(minutes=1))
1910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(minutes=1.0/60), td(seconds=1))
1920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(seconds=0.001), td(milliseconds=1))
1930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(milliseconds=0.001), td(microseconds=1))
1940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_computations(self):
1960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq = self.assertEqual
1970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td = timedelta
1980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
1990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = td(7) # One week
2000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = td(0, 60) # One minute
2010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        c = td(0, 0, 1000) # One millisecond
2020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(a+b+c, td(7, 60, 1000))
2030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(a-b, td(6, 24*3600 - 60))
2040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(-a, td(-7))
2050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(+a, td(7))
2060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(-b, td(-1, 24*3600 - 60))
2070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(-c, td(-1, 24*3600 - 1, 999000))
2080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(abs(a), a)
2090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(abs(-a), a)
2100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(6, 24*3600), a)
2110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(0, 0, 60*1000000), b)
2120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(a*10, td(70))
2130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(a*10, 10*a)
2140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(a*10L, 10*a)
2150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(b*10, td(0, 600))
2160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(10*b, td(0, 600))
2170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(b*10L, td(0, 600))
2180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(c*10, td(0, 0, 10000))
2190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(10*c, td(0, 0, 10000))
2200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(c*10L, td(0, 0, 10000))
2210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(a*-1, -a)
2220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(b*-2, -b-b)
2230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(c*-2, -c+-c)
2240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(b*(60*24), (b*60)*24)
2250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(b*(60*24), (60*b)*24)
2260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(c*1000, td(0, 1))
2270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(1000*c, td(0, 1))
2280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(a//7, td(1))
2290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(b//10, td(0, 6))
2300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(c//1000, td(0, 0, 1))
2310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(a//10, td(0, 7*24*360))
2320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(a//3600000, td(0, 0, 7*24*1000))
2330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Issue #11576
2350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(999999999, 86399, 999999) - td(999999999, 86399, 999998),
2360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi           td(0, 0, 1))
2370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(999999999, 1, 1) - td(999999999, 1, 0),
2380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi           td(0, 0, 1))
2390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_disallowed_computations(self):
2420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = timedelta(42)
2430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Add/sub ints, longs, floats should be illegal
2450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in 1, 1L, 1.0:
2460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: a+i)
2470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: a-i)
2480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: i+a)
2490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: i-a)
2500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Mul/div by float isn't supported.
2520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        x = 2.3
2530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a*x)
2540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: x*a)
2550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a/x)
2560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: x/a)
2570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a // x)
2580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: x // a)
2590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Division of int by timedelta doesn't make sense.
2610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Division by zero doesn't make sense.
2620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for zero in 0, 0L:
2630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: zero // a)
2640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(ZeroDivisionError, lambda: a // zero)
2650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_basic_attributes(self):
2670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        days, seconds, us = 1, 7, 31
2680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td = timedelta(days, seconds, us)
2690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(td.days, days)
2700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(td.seconds, seconds)
2710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(td.microseconds, us)
2720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_total_seconds(self):
2740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td = timedelta(days=365)
2750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(td.total_seconds(), 31536000.0)
2760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for total_seconds in [123456.789012, -123456.789012, 0.123456, 0, 1e6]:
2770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            td = timedelta(seconds=total_seconds)
2780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(td.total_seconds(), total_seconds)
2790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Issue8644: Test that td.total_seconds() has the same
2800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # accuracy as td / timedelta(seconds=1).
2810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for ms in [-1, -2, -123]:
2820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            td = timedelta(microseconds=ms)
2830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(td.total_seconds(),
2840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ((24*3600*td.days + td.seconds)*10**6
2850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                              + td.microseconds)/10**6)
2860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_carries(self):
2880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = timedelta(days=100,
2890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       weeks=-7,
2900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       hours=-24*(100-49),
2910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       minutes=-3,
2920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       seconds=12,
2930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       microseconds=(3*60 - 12) * 1e6 + 1)
2940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = timedelta(microseconds=1)
2950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
2960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
2970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_hash_equality(self):
2980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = timedelta(days=100,
2990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       weeks=-7,
3000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       hours=-24*(100-49),
3010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       minutes=-3,
3020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       seconds=12,
3030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       microseconds=(3*60 - 12) * 1000000)
3040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = timedelta()
3050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(t1), hash(t2))
3060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 += timedelta(weeks=7)
3080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 += timedelta(days=7*7)
3090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
3100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(t1), hash(t2))
3110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = {t1: 1}
3130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d[t2] = 2
3140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(d), 1)
3150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d[t1], 2)
3160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling(self):
3180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 12, 34, 56
3190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = timedelta(*args)
3200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
3210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
3220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
3230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
3240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_compare(self):
3260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = timedelta(2, 3, 4)
3270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = timedelta(2, 3, 4)
3280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 == t2)
3290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 <= t2)
3300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 >= t2)
3310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 != t2)
3320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 < t2)
3330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 > t2)
3340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cmp(t1, t2), 0)
3350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cmp(t2, t1), 0)
3360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for args in (3, 3, 3), (2, 4, 4), (2, 3, 5):
3380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            t2 = timedelta(*args)   # this is larger than t1
3390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 < t2)
3400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 > t1)
3410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 <= t2)
3420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 >= t1)
3430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 != t2)
3440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 != t1)
3450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 == t2)
3460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 == t1)
3470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 > t2)
3480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 < t1)
3490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 >= t2)
3500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 <= t1)
3510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(cmp(t1, t2), -1)
3520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(cmp(t2, t1), 1)
3530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for badarg in OTHERSTUFF:
3550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t1 == badarg, False)
3560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t1 != badarg, True)
3570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(badarg == t1, False)
3580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(badarg != t1, True)
3590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 <= badarg)
3610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 < badarg)
3620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 > badarg)
3630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 >= badarg)
3640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg <= t1)
3650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg < t1)
3660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg > t1)
3670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg >= t1)
3680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_str(self):
3700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td = timedelta
3710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq = self.assertEqual
3720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(str(td(1)), "1 day, 0:00:00")
3740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(str(td(-1)), "-1 day, 0:00:00")
3750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(str(td(2)), "2 days, 0:00:00")
3760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(str(td(-2)), "-2 days, 0:00:00")
3770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(str(td(hours=12, minutes=58, seconds=59)), "12:58:59")
3790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(str(td(hours=2, minutes=3, seconds=4)), "2:03:04")
3800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(str(td(weeks=-30, hours=23, minutes=12, seconds=34)),
3810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi           "-210 days, 23:12:34")
3820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(str(td(milliseconds=1)), "0:00:00.001000")
3840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(str(td(microseconds=3)), "0:00:00.000003")
3850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(str(td(days=999999999, hours=23, minutes=59, seconds=59,
3870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                   microseconds=999999)),
3880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi           "999999999 days, 23:59:59.999999")
3890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_roundtrip(self):
3910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for td in (timedelta(days=999999999, hours=23, minutes=59,
3920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             seconds=59, microseconds=999999),
3930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                   timedelta(days=-999999999),
3940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                   timedelta(days=1, seconds=2, microseconds=3)):
3950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
3960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Verify td -> string -> td identity.
3970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            s = repr(td)
3980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(s.startswith('datetime.'))
3990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            s = s[9:]
4000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            td2 = eval(s)
4010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(td, td2)
4020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Verify identity via reconstructing from pieces.
4040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            td2 = timedelta(td.days, td.seconds, td.microseconds)
4050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(td, td2)
4060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_resolution_info(self):
4080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(timedelta.min, timedelta)
4090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(timedelta.max, timedelta)
4100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(timedelta.resolution, timedelta)
4110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(timedelta.max > timedelta.min)
4120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(timedelta.min, timedelta(-999999999))
4130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(timedelta.max, timedelta(999999999, 24*3600-1, 1e6-1))
4140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(timedelta.resolution, timedelta(0, 0, 1))
4150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_overflow(self):
4170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tiny = timedelta.resolution
4180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td = timedelta.min + tiny
4200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td -= tiny  # no problem
4210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(OverflowError, td.__sub__, tiny)
4220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(OverflowError, td.__add__, -tiny)
4230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td = timedelta.max - tiny
4250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td += tiny  # no problem
4260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(OverflowError, td.__add__, tiny)
4270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(OverflowError, td.__sub__, -tiny)
4280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(OverflowError, lambda: -timedelta.max)
4300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_microsecond_rounding(self):
4320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td = timedelta
4330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq = self.assertEqual
4340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Single-field rounding.
4360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(milliseconds=0.4/1000), td(0))    # rounds to 0
4370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(milliseconds=-0.4/1000), td(0))    # rounds to 0
4380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(milliseconds=0.6/1000), td(microseconds=1))
4390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(milliseconds=-0.6/1000), td(microseconds=-1))
4400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Rounding due to contributions from more than one field.
4420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        us_per_hour = 3600e6
4430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        us_per_day = us_per_hour * 24
4440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(days=.4/us_per_day), td(0))
4450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(hours=.2/us_per_hour), td(0))
4460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(days=.4/us_per_day, hours=.2/us_per_hour), td(microseconds=1))
4470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(days=-.4/us_per_day), td(0))
4490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(hours=-.2/us_per_hour), td(0))
4500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        eq(td(days=-.4/us_per_day, hours=-.2/us_per_hour), td(microseconds=-1))
4510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_massive_normalization(self):
4530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        td = timedelta(microseconds=-1)
4540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((td.days, td.seconds, td.microseconds),
4550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         (-1, 24*3600-1, 999999))
4560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_bool(self):
4580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(timedelta(1))
4590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(timedelta(0, 1))
4600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(timedelta(0, 0, 1))
4610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(timedelta(microseconds=1))
4620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not timedelta(0))
4630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_subclass_timedelta(self):
4650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class T(timedelta):
4670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            @staticmethod
4680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def from_td(td):
4690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return T(td.days, td.seconds, td.microseconds)
4700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def as_hours(self):
4720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                sum = (self.days * 24 +
4730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       self.seconds / 3600.0 +
4740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                       self.microseconds / 3600e6)
4750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return round(sum)
4760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = T(days=1)
4780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(type(t1) is T)
4790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.as_hours(), 24)
4800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = T(days=-1, seconds=-3600)
4820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(type(t2) is T)
4830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.as_hours(), -25)
4840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t3 = t1 + t2
4860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(type(t3) is timedelta)
4870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t4 = T.from_td(t3)
4880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(type(t4) is T)
4890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.days, t4.days)
4900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.seconds, t4.seconds)
4910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.microseconds, t4.microseconds)
4920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t3), str(t4))
4930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t4.as_hours(), -1)
4940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#############################################################################
4960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# date tests
4970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
4980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestDateOnly(unittest.TestCase):
4990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Tests here won't pass if also run on datetime objects, so don't
5000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # subclass this to test datetimes too.
5010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_delta_non_days_ignored(self):
5030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = date(2000, 1, 2)
5040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        delta = timedelta(days=1, hours=2, minutes=3, seconds=4,
5050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          microseconds=5)
5060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        days = timedelta(delta.days)
5070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(days, timedelta(1))
5080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = dt + delta
5100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2, dt + days)
5110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = delta + dt
5130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2, dt + days)
5140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = dt - delta
5160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2, dt - days)
5170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        delta = -delta
5190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        days = timedelta(delta.days)
5200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(days, timedelta(-2))
5210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = dt + delta
5230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2, dt + days)
5240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = delta + dt
5260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2, dt + days)
5270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = dt - delta
5290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2, dt - days)
5300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass SubclassDate(date):
5320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    sub_var = 1
5330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestDate(HarmlessMixedComparison, unittest.TestCase):
5350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Tests here should pass for both dates and datetimes, except for a
5360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # few tests that TestDateTime overrides.
5370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    theclass = date
5390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_basic_attributes(self):
5410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = self.theclass(2002, 3, 1)
5420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.year, 2002)
5430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.month, 3)
5440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.day, 1)
5450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_roundtrip(self):
5470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for dt in (self.theclass(1, 2, 3),
5480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                   self.theclass.today()):
5490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Verify dt -> string -> date identity.
5500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            s = repr(dt)
5510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(s.startswith('datetime.'))
5520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            s = s[9:]
5530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dt2 = eval(s)
5540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(dt, dt2)
5550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Verify identity via reconstructing from pieces.
5570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dt2 = self.theclass(dt.year, dt.month, dt.day)
5580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(dt, dt2)
5590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_ordinal_conversions(self):
5610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Check some fixed values.
5620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for y, m, d, n in [(1, 1, 1, 1),      # calendar origin
5630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           (1, 12, 31, 365),
5640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           (2, 1, 1, 366),
5650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           # first example from "Calendrical Calculations"
5660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           (1945, 11, 12, 710347)]:
5670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(y, m, d)
5680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(n, d.toordinal())
5690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            fromord = self.theclass.fromordinal(n)
5700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d, fromord)
5710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if hasattr(fromord, "hour"):
5720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # if we're checking something fancier than a date, verify
5730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # the extra fields have been zeroed out
5740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(fromord.hour, 0)
5750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(fromord.minute, 0)
5760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(fromord.second, 0)
5770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(fromord.microsecond, 0)
5780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Check first and last days of year spottily across the whole
5800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # range of years supported.
5810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for year in xrange(MINYEAR, MAXYEAR+1, 7):
5820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Verify (year, 1, 1) -> ordinal -> y, m, d is identity.
5830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(year, 1, 1)
5840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            n = d.toordinal()
5850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d2 = self.theclass.fromordinal(n)
5860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d, d2)
5870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Verify that moving back a day gets to the end of year-1.
5880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if year > 1:
5890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                d = self.theclass.fromordinal(n-1)
5900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                d2 = self.theclass(year-1, 12, 31)
5910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(d, d2)
5920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(d2.toordinal(), n-1)
5930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
5940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Test every day in a leap-year and a non-leap year.
5950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dim = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
5960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for year, isleap in (2000, True), (2002, False):
5970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            n = self.theclass(year, 1, 1).toordinal()
5980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for month, maxday in zip(range(1, 13), dim):
5990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if month == 2 and isleap:
6000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    maxday += 1
6010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                for day in range(1, maxday+1):
6020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    d = self.theclass(year, month, day)
6030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.assertEqual(d.toordinal(), n)
6040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.assertEqual(d, self.theclass.fromordinal(n))
6050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    n += 1
6060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_extreme_ordinals(self):
6080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = self.theclass.min
6090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = self.theclass(a.year, a.month, a.day)  # get rid of time parts
6100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        aord = a.toordinal()
6110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = a.fromordinal(aord)
6120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a, b)
6130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, lambda: a.fromordinal(aord - 1))
6150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = a + timedelta(days=1)
6170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(b.toordinal(), aord + 1)
6180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(b, self.theclass.fromordinal(aord + 1))
6190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = self.theclass.max
6210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = self.theclass(a.year, a.month, a.day)  # get rid of time parts
6220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        aord = a.toordinal()
6230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = a.fromordinal(aord)
6240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a, b)
6250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, lambda: a.fromordinal(aord + 1))
6270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = a - timedelta(days=1)
6290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(b.toordinal(), aord - 1)
6300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(b, self.theclass.fromordinal(aord - 1))
6310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_bad_constructor_arguments(self):
6330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad years
6340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(MINYEAR, 1, 1)  # no exception
6350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(MAXYEAR, 1, 1)  # no exception
6360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1)
6370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1)
6380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad months
6390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 1, 1)    # no exception
6400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 12, 1)   # no exception
6410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 0, 1)
6420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 13, 1)
6430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad days
6440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 2, 29)   # no exception
6450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2004, 2, 29)   # no exception
6460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2400, 2, 29)   # no exception
6470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 2, 30)
6480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2001, 2, 29)
6490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2100, 2, 29)
6500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 1900, 2, 29)
6510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 1, 0)
6520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 1, 32)
6530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_hash_equality(self):
6550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.theclass(2000, 12, 31)
6560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # same thing
6570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e = self.theclass(2000, 12, 31)
6580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d, e)
6590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(d), hash(e))
6600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic = {d: 1}
6620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic[e] = 2
6630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(dic), 1)
6640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[d], 2)
6650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[e], 2)
6660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.theclass(2001,  1,  1)
6680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # same thing
6690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e = self.theclass(2001,  1,  1)
6700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d, e)
6710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(d), hash(e))
6720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic = {d: 1}
6740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic[e] = 2
6750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(dic), 1)
6760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[d], 2)
6770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[e], 2)
6780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_computations(self):
6800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = self.theclass(2002, 1, 31)
6810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = self.theclass(1956, 1, 31)
6820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        diff = a-b
6840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4)))
6850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(diff.seconds, 0)
6860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(diff.microseconds, 0)
6870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
6880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        day = timedelta(1)
6890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        week = timedelta(7)
6900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = self.theclass(2002, 3, 2)
6910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a + day, self.theclass(2002, 3, 3))
6920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(day + a, self.theclass(2002, 3, 3))
6930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - day, self.theclass(2002, 3, 1))
6940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(-day + a, self.theclass(2002, 3, 1))
6950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a + week, self.theclass(2002, 3, 9))
6960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - week, self.theclass(2002, 2, 23))
6970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a + 52*week, self.theclass(2003, 3, 1))
6980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - 52*week, self.theclass(2001, 3, 3))
6990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a + week) - a, week)
7000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a + day) - a, day)
7010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a - week) - a, -week)
7020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a - day) - a, -day)
7030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a + week), -week)
7040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a + day), -day)
7050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a - week), week)
7060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a - day), day)
7070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Add/sub ints, longs, floats should be illegal
7090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in 1, 1L, 1.0:
7100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: a+i)
7110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: a-i)
7120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: i+a)
7130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: i-a)
7140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # delta - date is senseless.
7160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: day - a)
7170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # mixing date and (delta or date) via * or // is senseless
7180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: day * a)
7190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a * day)
7200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: day // a)
7210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a // day)
7220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a * a)
7230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a // a)
7240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # date + date is senseless
7250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a + a)
7260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_overflow(self):
7280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tiny = self.theclass.resolution
7290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for delta in [tiny, timedelta(1), timedelta(2)]:
7310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dt = self.theclass.min + delta
7320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dt -= delta  # no problem
7330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(OverflowError, dt.__sub__, delta)
7340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(OverflowError, dt.__add__, -delta)
7350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dt = self.theclass.max - delta
7370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dt += delta  # no problem
7380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(OverflowError, dt.__add__, delta)
7390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(OverflowError, dt.__sub__, -delta)
7400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_fromtimestamp(self):
7420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import time
7430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try an arbitrary fixed value.
7450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        year, month, day = 1999, 9, 19
7460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        ts = time.mktime((year, month, day, 0, 0, 0, 0, 0, -1))
7470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.theclass.fromtimestamp(ts)
7480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d.year, year)
7490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d.month, month)
7500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d.day, day)
7510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_insane_fromtimestamp(self):
7530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # It's possible that some platform maps time_t to double,
7540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # and that this test will fail there.  This test should
7550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # exempt such platforms (provided they return reasonable
7560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # results!).
7570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for insane in -1e200, 1e200:
7580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(ValueError, self.theclass.fromtimestamp,
7590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                              insane)
7600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_today(self):
7620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import time
7630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # We claim that today() is like fromtimestamp(time.time()), so
7650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # prove it.
7660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for dummy in range(3):
7670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            today = self.theclass.today()
7680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            ts = time.time()
7690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            todayagain = self.theclass.fromtimestamp(ts)
7700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if today == todayagain:
7710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
7720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # There are several legit reasons that could fail:
7730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # 1. It recently became midnight, between the today() and the
7740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            #    time() calls.
7750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # 2. The platform time() has such fine resolution that we'll
7760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            #    never get the same value twice.
7770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # 3. The platform time() has poor resolution, and we just
7780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            #    happened to call today() right before a resolution quantum
7790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            #    boundary.
7800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # 4. The system clock got fiddled between calls.
7810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # In any case, wait a little while and try again.
7820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            time.sleep(0.1)
7830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # It worked or it didn't.  If it didn't, assume it's reason #2, and
7850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # let the test pass if they're within half a second of each other.
7860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(today == todayagain or
7870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        abs(todayagain - today) < timedelta(seconds=0.5))
7880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_weekday(self):
7900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in range(7):
7910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # March 4, 2002 is a Monday
7920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(self.theclass(2002, 3, 4+i).weekday(), i)
7930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(self.theclass(2002, 3, 4+i).isoweekday(), i+1)
7940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # January 2, 1956 is a Monday
7950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(self.theclass(1956, 1, 2+i).weekday(), i)
7960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(self.theclass(1956, 1, 2+i).isoweekday(), i+1)
7970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
7980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_isocalendar(self):
7990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Check examples from
8000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
8010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in range(7):
8020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(2003, 12, 22+i)
8030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.isocalendar(), (2003, 52, i+1))
8040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(2003, 12, 29) + timedelta(i)
8050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.isocalendar(), (2004, 1, i+1))
8060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(2004, 1, 5+i)
8070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.isocalendar(), (2004, 2, i+1))
8080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(2009, 12, 21+i)
8090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.isocalendar(), (2009, 52, i+1))
8100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(2009, 12, 28) + timedelta(i)
8110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.isocalendar(), (2009, 53, i+1))
8120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(2010, 1, 4+i)
8130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.isocalendar(), (2010, 1, i+1))
8140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_iso_long_years(self):
8160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Calculate long ISO years and compare to table from
8170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
8180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        ISO_LONG_YEARS_TABLE = """
8190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi              4   32   60   88
8200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi              9   37   65   93
8210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi             15   43   71   99
8220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi             20   48   76
8230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi             26   54   82
8240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            105  133  161  189
8260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            111  139  167  195
8270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            116  144  172
8280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            122  150  178
8290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            128  156  184
8300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            201  229  257  285
8320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            207  235  263  291
8330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            212  240  268  296
8340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            218  246  274
8350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            224  252  280
8360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            303  331  359  387
8380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            308  336  364  392
8390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            314  342  370  398
8400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            320  348  376
8410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            325  353  381
8420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        """
8430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        iso_long_years = map(int, ISO_LONG_YEARS_TABLE.split())
8440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        iso_long_years.sort()
8450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        L = []
8460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in range(400):
8470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(2000+i, 12, 31)
8480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d1 = self.theclass(1600+i, 12, 31)
8490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.isocalendar()[1:], d1.isocalendar()[1:])
8500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if d.isocalendar()[1] == 53:
8510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                L.append(i)
8520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(L, iso_long_years)
8530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_isoformat(self):
8550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(2, 3, 2)
8560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), "0002-03-02")
8570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_ctime(self):
8590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(2002, 3, 2)
8600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.ctime(), "Sat Mar  2 00:00:00 2002")
8610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_strftime(self):
8630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(2005, 3, 2)
8640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.strftime("m:%m d:%d y:%y"), "m:03 d:02 y:05")
8650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.strftime(""), "") # SF bug #761337
8660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.strftime('x'*1000), 'x'*1000) # SF bug #1556784
8670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t.strftime) # needs an arg
8690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t.strftime, "one", "two") # too many args
8700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t.strftime, 42) # arg wrong type
8710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # test that unicode input is allowed (issue 2782)
8730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.strftime(u"%m"), "03")
8740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # A naive object replaces %z and %Z w/ empty strings.
8760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
8770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #make sure that invalid format specifiers are handled correctly
8790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #self.assertRaises(ValueError, t.strftime, "%e")
8800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #self.assertRaises(ValueError, t.strftime, "%")
8810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #self.assertRaises(ValueError, t.strftime, "%#")
8820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #oh well, some systems just ignore those invalid ones.
8840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #at least, excercise them to make sure that no crashes
8850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #are generated
8860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for f in ["%e", "%", "%#"]:
8870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            try:
8880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                t.strftime(f)
8890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            except ValueError:
8900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                pass
8910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #check that this standard extension works
8930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t.strftime("%f")
8940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
8960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_format(self):
8970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = self.theclass(2007, 9, 10)
8980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.__format__(''), str(dt))
8990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # check that a derived class's __str__() gets called
9010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class A(self.theclass):
9020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __str__(self):
9030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return 'A'
9040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = A(2007, 9, 10)
9050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a.__format__(''), 'A')
9060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # check that a derived class's strftime gets called
9080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class B(self.theclass):
9090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def strftime(self, format_spec):
9100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return 'B'
9110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = B(2007, 9, 10)
9120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(b.__format__(''), str(dt))
9130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for fmt in ["m:%m d:%d y:%y",
9150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    "m:%m d:%d y:%y H:%H M:%M S:%S",
9160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    "%z %Z",
9170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    ]:
9180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(dt.__format__(fmt), dt.strftime(fmt))
9190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(a.__format__(fmt), dt.strftime(fmt))
9200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(b.__format__(fmt), 'B')
9210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_resolution_info(self):
9230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(self.theclass.min, self.theclass)
9240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(self.theclass.max, self.theclass)
9250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(self.theclass.resolution, timedelta)
9260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(self.theclass.max > self.theclass.min)
9270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_extreme_timedelta(self):
9290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        big = self.theclass.max - self.theclass.min
9300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds
9310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds
9320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # n == 315537897599999999 ~= 2**58.13
9330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        justasbig = timedelta(0, 0, n)
9340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(big, justasbig)
9350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.theclass.min + big, self.theclass.max)
9360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.theclass.max - big, self.theclass.min)
9370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_timetuple(self):
9390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in range(7):
9400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # January 2, 1956 is a Monday (0)
9410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(1956, 1, 2+i)
9420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            t = d.timetuple()
9430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t, (1956, 1, 2+i, 0, 0, 0, i, 2+i, -1))
9440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # February 1, 1956 is a Wednesday (2)
9450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(1956, 2, 1+i)
9460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            t = d.timetuple()
9470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t, (1956, 2, 1+i, 0, 0, 0, (2+i)%7, 32+i, -1))
9480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # March 1, 1956 is a Thursday (3), and is the 31+29+1 = 61st day
9490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # of the year.
9500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = self.theclass(1956, 3, 1+i)
9510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            t = d.timetuple()
9520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t, (1956, 3, 1+i, 0, 0, 0, (3+i)%7, 61+i, -1))
9530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t.tm_year, 1956)
9540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t.tm_mon, 3)
9550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t.tm_mday, 1+i)
9560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t.tm_hour, 0)
9570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t.tm_min, 0)
9580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t.tm_sec, 0)
9590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t.tm_wday, (3+i)%7)
9600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t.tm_yday, 61+i)
9610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t.tm_isdst, -1)
9620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling(self):
9640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 6, 7, 23
9650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = self.theclass(*args)
9660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
9670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
9680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
9690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
9700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_compare(self):
9720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(2, 3, 4)
9730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass(2, 3, 4)
9740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 == t2)
9750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 <= t2)
9760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 >= t2)
9770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 != t2)
9780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 < t2)
9790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 > t2)
9800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cmp(t1, t2), 0)
9810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cmp(t2, t1), 0)
9820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
9830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for args in (3, 3, 3), (2, 4, 4), (2, 3, 5):
9840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            t2 = self.theclass(*args)   # this is larger than t1
9850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 < t2)
9860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 > t1)
9870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 <= t2)
9880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 >= t1)
9890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 != t2)
9900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 != t1)
9910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 == t2)
9920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 == t1)
9930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 > t2)
9940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 < t1)
9950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 >= t2)
9960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 <= t1)
9970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(cmp(t1, t2), -1)
9980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(cmp(t2, t1), 1)
9990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for badarg in OTHERSTUFF:
10010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t1 == badarg, False)
10020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t1 != badarg, True)
10030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(badarg == t1, False)
10040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(badarg != t1, True)
10050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 < badarg)
10070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 > badarg)
10080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 >= badarg)
10090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg <= t1)
10100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg < t1)
10110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg > t1)
10120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg >= t1)
10130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_mixed_compare(self):
10150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        our = self.theclass(2000, 4, 5)
10160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, cmp, our, 1)
10170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, cmp, 1, our)
10180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class AnotherDateTimeClass(object):
10200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __cmp__(self, other):
10210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                # Return "equal" so calling this can't be confused with
10220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                # compare-by-address (which never says "equal" for distinct
10230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                # objects).
10240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return 0
10250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            __hash__ = None # Silence Py3k warning
10260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # This still errors, because date and datetime comparison raise
10280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # TypeError instead of NotImplemented when they don't know what to
10290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # do, in order to stop comparison from falling back to the default
10300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # compare-by-address.
10310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        their = AnotherDateTimeClass()
10320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, cmp, our, their)
10330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Oops:  The next stab raises TypeError in the C implementation,
10340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # but not in the Python implementation of datetime.  The difference
10350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # is due to that the Python implementation defines __cmp__ but
10360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # the C implementation defines tp_richcompare.  This is more pain
10370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # to fix than it's worth, so commenting out the test.
10380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # self.assertEqual(cmp(their, our), 0)
10390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # But date and datetime comparison return NotImplemented instead if the
10410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # other object has a timetuple attr.  This gives the other object a
10420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # chance to do the comparison.
10430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class Comparable(AnotherDateTimeClass):
10440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def timetuple(self):
10450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return ()
10460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        their = Comparable()
10480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cmp(our, their), 0)
10490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cmp(their, our), 0)
10500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(our == their)
10510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(their == our)
10520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_bool(self):
10540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # All dates are considered true.
10550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(self.theclass.min)
10560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(self.theclass.max)
10570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_strftime_out_of_range(self):
10590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # For nasty technical reasons, we can't handle years before 1900.
10600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
10610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cls(1900, 1, 1).strftime("%Y"), "1900")
10620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for y in 1, 49, 51, 99, 100, 1000, 1899:
10630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(ValueError, cls(y, 1, 1).strftime, "%Y")
10640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_replace(self):
10660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
10670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = [1, 2, 3]
10680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(*args)
10690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(base, base.replace())
10700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        i = 0
10720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for name, newval in (("year", 2),
10730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("month", 3),
10740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("day", 4)):
10750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs = args[:]
10760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs[i] = newval
10770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            expected = cls(*newargs)
10780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = base.replace(**{name: newval})
10790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
10800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            i += 1
10810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Out of bounds.
10830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(2000, 2, 29)
10840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, year=2001)
10850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_subclass_date(self):
10870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class C(self.theclass):
10890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            theAnswer = 42
10900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __new__(cls, *args, **kws):
10920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                temp = kws.copy()
10930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                extra = temp.pop('extra')
10940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                result = self.theclass.__new__(cls, *args, **temp)
10950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                result.extra = extra
10960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return result
10970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
10980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def newmeth(self, start):
10990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return start + self.year + self.month
11000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 2003, 4, 14
11020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt1 = self.theclass(*args)
11040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = C(*args, **{'extra': 7})
11050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.__class__, C)
11070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.theAnswer, 42)
11080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.extra, 7)
11090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt1.toordinal(), dt2.toordinal())
11100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month - 7)
11110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling_subclass_date(self):
11130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 6, 7, 23
11150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = SubclassDate(*args)
11160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
11170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
11180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
11190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
11200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_backdoor_resistance(self):
11220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # For fast unpickling, the constructor accepts a pickle string.
11230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # This is a low-overhead backdoor.  A user can (by intent or
11240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # mistake) pass a string directly, which (if it's the right length)
11250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # will get treated like a pickle, and bypass the normal sanity
11260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # checks in the constructor.  This can create insane objects.
11270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # The constructor doesn't want to burn the time to validate all
11280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # fields, but does check the month field.  This stops, e.g.,
11290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # datetime.datetime('1995-03-25') from yielding an insane object.
11300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = '1995-03-25'
11310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if not issubclass(self.theclass, datetime):
11320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            base = base[:4]
11330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for month_byte in '9', chr(0), chr(13), '\xff':
11340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, self.theclass,
11350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                         base[:2] + month_byte + base[3:])
11360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for ord_byte in range(1, 13):
11370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # This shouldn't blow up because of the month byte alone.  If
11380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # the implementation changes to do more-careful checking, it may
11390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # blow up because other fields are insane.
11400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.theclass(base[:2] + chr(ord_byte) + base[3:])
11410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#############################################################################
11430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# datetime tests
11440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass SubclassDatetime(datetime):
11460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    sub_var = 1
11470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestDateTime(TestDate):
11490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    theclass = datetime
11510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_basic_attributes(self):
11530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = self.theclass(2002, 3, 1, 12, 0)
11540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.year, 2002)
11550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.month, 3)
11560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.day, 1)
11570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.hour, 12)
11580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.minute, 0)
11590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.second, 0)
11600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.microsecond, 0)
11610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_basic_attributes_nonzero(self):
11630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Make sure all attributes are non-zero so bugs in
11640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bit-shifting access show up.
11650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = self.theclass(2002, 3, 1, 12, 59, 59, 8000)
11660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.year, 2002)
11670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.month, 3)
11680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.day, 1)
11690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.hour, 12)
11700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.minute, 59)
11710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.second, 59)
11720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.microsecond, 8000)
11730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_roundtrip(self):
11750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7),
11760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                   self.theclass.now()):
11770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Verify dt -> string -> datetime identity.
11780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            s = repr(dt)
11790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(s.startswith('datetime.'))
11800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            s = s[9:]
11810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dt2 = eval(s)
11820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(dt, dt2)
11830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Verify identity via reconstructing from pieces.
11850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dt2 = self.theclass(dt.year, dt.month, dt.day,
11860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                dt.hour, dt.minute, dt.second,
11870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                dt.microsecond)
11880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(dt, dt2)
11890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_isoformat(self):
11910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(2, 3, 2, 4, 5, 1, 123)
11920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(),    "0002-03-02T04:05:01.000123")
11930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat('T'), "0002-03-02T04:05:01.000123")
11940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123")
11950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat('\x00'), "0002-03-02\x0004:05:01.000123")
11960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # str is ISO format with the separator forced to a blank.
11970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t), "0002-03-02 04:05:01.000123")
11980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
11990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(2, 3, 2)
12000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(),    "0002-03-02T00:00:00")
12010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat('T'), "0002-03-02T00:00:00")
12020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(' '), "0002-03-02 00:00:00")
12030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # str is ISO format with the separator forced to a blank.
12040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t), "0002-03-02 00:00:00")
12050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_format(self):
12070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = self.theclass(2007, 9, 10, 4, 5, 1, 123)
12080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.__format__(''), str(dt))
12090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # check that a derived class's __str__() gets called
12110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class A(self.theclass):
12120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __str__(self):
12130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return 'A'
12140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = A(2007, 9, 10, 4, 5, 1, 123)
12150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a.__format__(''), 'A')
12160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # check that a derived class's strftime gets called
12180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class B(self.theclass):
12190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def strftime(self, format_spec):
12200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return 'B'
12210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = B(2007, 9, 10, 4, 5, 1, 123)
12220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(b.__format__(''), str(dt))
12230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for fmt in ["m:%m d:%d y:%y",
12250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    "m:%m d:%d y:%y H:%H M:%M S:%S",
12260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    "%z %Z",
12270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    ]:
12280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(dt.__format__(fmt), dt.strftime(fmt))
12290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(a.__format__(fmt), dt.strftime(fmt))
12300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(b.__format__(fmt), 'B')
12310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_more_ctime(self):
12330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Test fields that TestDate doesn't touch.
12340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import time
12350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(2002, 3, 2, 18, 3, 5, 123)
12370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.ctime(), "Sat Mar  2 18:03:05 2002")
12380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Oops!  The next line fails on Win2K under MSVC 6, so it's commented
12390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # out.  The difference is that t.ctime() produces " 2" for the day,
12400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # but platform ctime() produces "02" for the day.  According to
12410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # C99, t.ctime() is correct here.
12420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # self.assertEqual(t.ctime(), time.ctime(time.mktime(t.timetuple())))
12430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # So test a case where that difference doesn't matter.
12450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(2002, 3, 22, 18, 3, 5, 123)
12460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.ctime(), time.ctime(time.mktime(t.timetuple())))
12470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_tz_independent_comparing(self):
12490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt1 = self.theclass(2002, 3, 1, 9, 0, 0)
12500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = self.theclass(2002, 3, 1, 10, 0, 0)
12510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt3 = self.theclass(2002, 3, 1, 9, 0, 0)
12520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt1, dt3)
12530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(dt2 > dt3)
12540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Make sure comparison doesn't forget microseconds, and isn't done
12560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # via comparing a float timestamp (an IEEE double doesn't have enough
12570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # precision to span microsecond resolution across years 1 thru 9999,
12580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # so comparing via timestamp necessarily calls some distinct values
12590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # equal).
12600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998)
12610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        us = timedelta(microseconds=1)
12620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = dt1 + us
12630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2 - dt1, us)
12640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(dt1 < dt2)
12650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_strftime_with_bad_tzname_replace(self):
12670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # verify ok if tzinfo.tzname().replace() returns a non-string
12680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class MyTzInfo(FixedOffset):
12690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def tzname(self, dt):
12700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                class MyStr(str):
12710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    def replace(self, *args):
12720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        return None
12730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return MyStr('name')
12740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(2005, 3, 2, 0, 0, 0, 0, MyTzInfo(3, 'name'))
12750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t.strftime, '%Z')
12760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
12770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_bad_constructor_arguments(self):
12780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad years
12790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(MINYEAR, 1, 1)  # no exception
12800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(MAXYEAR, 1, 1)  # no exception
12810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1)
12820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1)
12830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad months
12840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 1, 1)    # no exception
12850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 12, 1)   # no exception
12860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 0, 1)
12870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 13, 1)
12880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad days
12890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 2, 29)   # no exception
12900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2004, 2, 29)   # no exception
12910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2400, 2, 29)   # no exception
12920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 2, 30)
12930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2001, 2, 29)
12940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2100, 2, 29)
12950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 1900, 2, 29)
12960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 1, 0)
12970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 1, 32)
12980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad hours
12990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 1, 31, 0)    # no exception
13000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 1, 31, 23)   # no exception
13010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, -1)
13020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 24)
13030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad minutes
13040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 1, 31, 23, 0)    # no exception
13050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 1, 31, 23, 59)   # no exception
13060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, -1)
13070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 60)
13080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad seconds
13090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 1, 31, 23, 59, 0)    # no exception
13100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 1, 31, 23, 59, 59)   # no exception
13110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, -1)
13120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, 60)
13130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad microseconds
13140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 1, 31, 23, 59, 59, 0)    # no exception
13150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(2000, 1, 31, 23, 59, 59, 999999)   # no exception
13160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass,
13170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          2000, 1, 31, 23, 59, 59, -1)
13180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass,
13190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          2000, 1, 31, 23, 59, 59,
13200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          1000000)
13210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_hash_equality(self):
13230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.theclass(2000, 12, 31, 23, 30, 17)
13240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e = self.theclass(2000, 12, 31, 23, 30, 17)
13250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d, e)
13260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(d), hash(e))
13270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic = {d: 1}
13290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic[e] = 2
13300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(dic), 1)
13310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[d], 2)
13320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[e], 2)
13330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.theclass(2001,  1,  1,  0,  5, 17)
13350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e = self.theclass(2001,  1,  1,  0,  5, 17)
13360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d, e)
13370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(d), hash(e))
13380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic = {d: 1}
13400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic[e] = 2
13410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(dic), 1)
13420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[d], 2)
13430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[e], 2)
13440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
13450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_computations(self):
13460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = self.theclass(2002, 1, 31)
13470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = self.theclass(1956, 1, 31)
13480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        diff = a-b
13490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4)))
13500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(diff.seconds, 0)
13510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(diff.microseconds, 0)
13520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = self.theclass(2002, 3, 2, 17, 6)
13530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        millisec = timedelta(0, 0, 1000)
13540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        hour = timedelta(0, 3600)
13550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        day = timedelta(1)
13560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        week = timedelta(7)
13570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a + hour, self.theclass(2002, 3, 2, 18, 6))
13580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hour + a, self.theclass(2002, 3, 2, 18, 6))
13590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a + 10*hour, self.theclass(2002, 3, 3, 3, 6))
13600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - hour, self.theclass(2002, 3, 2, 16, 6))
13610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(-hour + a, self.theclass(2002, 3, 2, 16, 6))
13620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - hour, a + -hour)
13630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - 20*hour, self.theclass(2002, 3, 1, 21, 6))
13640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a + day, self.theclass(2002, 3, 3, 17, 6))
13650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - day, self.theclass(2002, 3, 1, 17, 6))
13660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a + week, self.theclass(2002, 3, 9, 17, 6))
13670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - week, self.theclass(2002, 2, 23, 17, 6))
13680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a + 52*week, self.theclass(2003, 3, 1, 17, 6))
13690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - 52*week, self.theclass(2001, 3, 3, 17, 6))
13700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a + week) - a, week)
13710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a + day) - a, day)
13720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a + hour) - a, hour)
13730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a + millisec) - a, millisec)
13740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a - week) - a, -week)
13750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a - day) - a, -day)
13760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a - hour) - a, -hour)
13770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual((a - millisec) - a, -millisec)
13780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a + week), -week)
13790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a + day), -day)
13800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a + hour), -hour)
13810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a + millisec), -millisec)
13820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a - week), week)
13830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a - day), day)
13840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a - hour), hour)
13850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (a - millisec), millisec)
13860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a + (week + day + hour + millisec),
13870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         self.theclass(2002, 3, 10, 18, 6, 0, 1000))
13880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a + (week + day + hour + millisec),
13890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         (((a + week) + day) + hour) + millisec)
13900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (week + day + hour + millisec),
13910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         self.theclass(2002, 2, 22, 16, 5, 59, 999000))
13920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a - (week + day + hour + millisec),
13930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         (((a - week) - day) - hour) - millisec)
13940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Add/sub ints, longs, floats should be illegal
13950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in 1, 1L, 1.0:
13960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: a+i)
13970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: a-i)
13980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: i+a)
13990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: i-a)
14000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # delta - datetime is senseless.
14020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: day - a)
14030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # mixing datetime and (delta or datetime) via * or // is senseless
14040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: day * a)
14050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a * day)
14060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: day // a)
14070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a // day)
14080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a * a)
14090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a // a)
14100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # datetime + datetime is senseless
14110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: a + a)
14120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling(self):
14140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 6, 7, 23, 20, 59, 1, 64**2
14150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = self.theclass(*args)
14160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
14170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
14180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
14190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
14200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_more_pickling(self):
14220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = self.theclass(2003, 2, 7, 16, 48, 37, 444116)
14230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        s = pickle.dumps(a)
14240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = pickle.loads(s)
14250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(b.year, 2003)
14260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(b.month, 2)
14270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(b.day, 7)
14280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling_subclass_datetime(self):
14300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 6, 7, 23, 20, 59, 1, 64**2
14310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = SubclassDatetime(*args)
14320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
14330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
14340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
14350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
14360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_more_compare(self):
14380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # The test_compare() inherited from TestDate covers the error cases.
14390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # We just want to test lexicographic ordering on the members datetime
14400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # has that date lacks.
14410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = [2000, 11, 29, 20, 58, 16, 999998]
14420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(*args)
14430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass(*args)
14440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 == t2)
14450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 <= t2)
14460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 >= t2)
14470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 != t2)
14480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 < t2)
14490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 > t2)
14500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cmp(t1, t2), 0)
14510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cmp(t2, t1), 0)
14520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in range(len(args)):
14540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs = args[:]
14550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs[i] = args[i] + 1
14560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            t2 = self.theclass(*newargs)   # this is larger than t1
14570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 < t2)
14580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 > t1)
14590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 <= t2)
14600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 >= t1)
14610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 != t2)
14620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 != t1)
14630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 == t2)
14640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 == t1)
14650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 > t2)
14660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 < t1)
14670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 >= t2)
14680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 <= t1)
14690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(cmp(t1, t2), -1)
14700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(cmp(t2, t1), 1)
14710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # A helper for timestamp constructor tests.
14740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def verify_field_equality(self, expected, got):
14750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(expected.tm_year, got.year)
14760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(expected.tm_mon, got.month)
14770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(expected.tm_mday, got.day)
14780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(expected.tm_hour, got.hour)
14790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(expected.tm_min, got.minute)
14800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(expected.tm_sec, got.second)
14810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_fromtimestamp(self):
14830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import time
14840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        ts = time.time()
14860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = time.localtime(ts)
14870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        got = self.theclass.fromtimestamp(ts)
14880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.verify_field_equality(expected, got)
14890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_utcfromtimestamp(self):
14910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import time
14920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        ts = time.time()
14940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = time.gmtime(ts)
14950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        got = self.theclass.utcfromtimestamp(ts)
14960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.verify_field_equality(expected, got)
14970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
14980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_microsecond_rounding(self):
14990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Test whether fromtimestamp "rounds up" floats that are less
15000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # than one microsecond smaller than an integer.
15010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(self.theclass.fromtimestamp(0.9999999),
15020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         self.theclass.fromtimestamp(1))
15030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_insane_fromtimestamp(self):
15050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # It's possible that some platform maps time_t to double,
15060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # and that this test will fail there.  This test should
15070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # exempt such platforms (provided they return reasonable
15080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # results!).
15090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for insane in -1e200, 1e200:
15100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(ValueError, self.theclass.fromtimestamp,
15110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                              insane)
15120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_insane_utcfromtimestamp(self):
15140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # It's possible that some platform maps time_t to double,
15150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # and that this test will fail there.  This test should
15160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # exempt such platforms (provided they return reasonable
15170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # results!).
15180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for insane in -1e200, 1e200:
15190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(ValueError, self.theclass.utcfromtimestamp,
15200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                              insane)
15210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps")
15220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_negative_float_fromtimestamp(self):
15230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # The result is tz-dependent; at least test that this doesn't
15240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # fail (like it did before bug 1646728 was fixed).
15250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass.fromtimestamp(-1.05)
15260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps")
15280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_negative_float_utcfromtimestamp(self):
15290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.theclass.utcfromtimestamp(-1.05)
15300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d, self.theclass(1969, 12, 31, 23, 59, 58, 950000))
15310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_utcnow(self):
15330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import time
15340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Call it a success if utcnow() and utcfromtimestamp() are within
15360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # a second of each other.
15370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tolerance = timedelta(seconds=1)
15380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for dummy in range(3):
15390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            from_now = self.theclass.utcnow()
15400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            from_timestamp = self.theclass.utcfromtimestamp(time.time())
15410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if abs(from_timestamp - from_now) <= tolerance:
15420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
15430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Else try again a few times.
15440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(abs(from_timestamp - from_now) <= tolerance)
15450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_strptime(self):
15470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import _strptime
15480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        string = '2004-12-01 13:02:47.197'
15500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        format = '%Y-%m-%d %H:%M:%S.%f'
15510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        result, frac = _strptime._strptime(string, format)
15520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = self.theclass(*(result[0:6]+(frac,)))
15530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        got = self.theclass.strptime(string, format)
15540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(expected, got)
15550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_more_timetuple(self):
15570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # This tests fields beyond those tested by the TestDate.test_timetuple.
15580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(2004, 12, 31, 6, 22, 33)
15590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.timetuple(), (2004, 12, 31, 6, 22, 33, 4, 366, -1))
15600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.timetuple(),
15610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         (t.year, t.month, t.day,
15620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          t.hour, t.minute, t.second,
15630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          t.weekday(),
15640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          t.toordinal() - date(t.year, 1, 1).toordinal() + 1,
15650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          -1))
15660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tt = t.timetuple()
15670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(tt.tm_year, t.year)
15680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(tt.tm_mon, t.month)
15690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(tt.tm_mday, t.day)
15700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(tt.tm_hour, t.hour)
15710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(tt.tm_min, t.minute)
15720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(tt.tm_sec, t.second)
15730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(tt.tm_wday, t.weekday())
15740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(tt.tm_yday, t.toordinal() -
15750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                     date(t.year, 1, 1).toordinal() + 1)
15760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(tt.tm_isdst, -1)
15770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_more_strftime(self):
15790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # This tests fields beyond those tested by the TestDate.test_strftime.
15800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(2004, 12, 31, 6, 22, 33, 47)
15810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.strftime("%m %d %y %f %S %M %H %j"),
15820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                    "12 31 04 000047 33 22 06 366")
15830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_extract(self):
15850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = self.theclass(2002, 3, 4, 18, 45, 3, 1234)
15860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.date(), date(2002, 3, 4))
15870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.time(), time(18, 45, 3, 1234))
15880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_combine(self):
15900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = date(2002, 3, 4)
15910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = time(18, 45, 3, 1234)
15920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = self.theclass(2002, 3, 4, 18, 45, 3, 1234)
15930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        combine = self.theclass.combine
15940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = combine(d, t)
15950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt, expected)
15960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
15970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = combine(time=t, date=d)
15980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt, expected)
15990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d, dt.date())
16010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t, dt.time())
16020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt, combine(dt.date(), dt.time()))
16030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, combine) # need an arg
16050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, combine, d) # need two args
16060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, combine, t, d) # args reversed
16070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, combine, d, t, 1) # too many args
16080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, combine, "date", "time") # wrong types
16090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_replace(self):
16110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
16120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = [1, 2, 3, 4, 5, 6, 7]
16130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(*args)
16140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(base, base.replace())
16150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        i = 0
16170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for name, newval in (("year", 2),
16180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("month", 3),
16190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("day", 4),
16200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("hour", 5),
16210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("minute", 6),
16220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("second", 7),
16230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("microsecond", 8)):
16240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs = args[:]
16250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs[i] = newval
16260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            expected = cls(*newargs)
16270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = base.replace(**{name: newval})
16280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
16290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            i += 1
16300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Out of bounds.
16320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(2000, 2, 29)
16330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, year=2001)
16340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_astimezone(self):
16360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Pretty boring!  The TZ test is more interesting here.  astimezone()
16370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # simply can't be applied to a naive object.
16380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = self.theclass.now()
16390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f = FixedOffset(44, "")
16400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, dt.astimezone) # not enough args
16410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, dt.astimezone, f, f) # too many args
16420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, dt.astimezone, dt) # arg wrong type
16430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, dt.astimezone, f) # naive
16440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, dt.astimezone, tz=f)  # naive
16450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class Bogus(tzinfo):
16470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): return None
16480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt): return timedelta(0)
16490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        bog = Bogus()
16500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, dt.astimezone, bog)   # naive
16510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class AlsoBogus(tzinfo):
16530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): return timedelta(0)
16540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt): return None
16550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        alsobog = AlsoBogus()
16560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, dt.astimezone, alsobog) # also naive
16570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_subclass_datetime(self):
16590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class C(self.theclass):
16610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            theAnswer = 42
16620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __new__(cls, *args, **kws):
16640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                temp = kws.copy()
16650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                extra = temp.pop('extra')
16660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                result = self.theclass.__new__(cls, *args, **temp)
16670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                result.extra = extra
16680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return result
16690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def newmeth(self, start):
16710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return start + self.year + self.month + self.second
16720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 2003, 4, 14, 12, 13, 41
16740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt1 = self.theclass(*args)
16760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = C(*args, **{'extra': 7})
16770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.__class__, C)
16790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.theAnswer, 42)
16800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.extra, 7)
16810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt1.toordinal(), dt2.toordinal())
16820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month +
16830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                          dt1.second - 7)
16840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass SubclassTime(time):
16860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    sub_var = 1
16870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestTime(HarmlessMixedComparison, unittest.TestCase):
16890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    theclass = time
16910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_basic_attributes(self):
16930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(12, 0)
16940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.hour, 12)
16950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.minute, 0)
16960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.second, 0)
16970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.microsecond, 0)
16980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
16990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_basic_attributes_nonzero(self):
17000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Make sure all attributes are non-zero so bugs in
17010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bit-shifting access show up.
17020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(12, 59, 59, 8000)
17030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.hour, 12)
17040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.minute, 59)
17050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.second, 59)
17060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.microsecond, 8000)
17070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_roundtrip(self):
17090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(1, 2, 3, 4)
17100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Verify t -> string -> time identity.
17120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        s = repr(t)
17130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(s.startswith('datetime.'))
17140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        s = s[9:]
17150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = eval(s)
17160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t, t2)
17170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Verify identity via reconstructing from pieces.
17190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass(t.hour, t.minute, t.second,
17200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           t.microsecond)
17210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t, t2)
17220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_comparing(self):
17240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = [1, 2, 3, 4]
17250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(*args)
17260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass(*args)
17270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 == t2)
17280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 <= t2)
17290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 >= t2)
17300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 != t2)
17310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 < t2)
17320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t1 > t2)
17330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cmp(t1, t2), 0)
17340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cmp(t2, t1), 0)
17350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for i in range(len(args)):
17370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs = args[:]
17380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs[i] = args[i] + 1
17390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            t2 = self.theclass(*newargs)   # this is larger than t1
17400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 < t2)
17410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 > t1)
17420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 <= t2)
17430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 >= t1)
17440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t1 != t2)
17450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t2 != t1)
17460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 == t2)
17470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 == t1)
17480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 > t2)
17490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 < t1)
17500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t1 >= t2)
17510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(not t2 <= t1)
17520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(cmp(t1, t2), -1)
17530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(cmp(t2, t1), 1)
17540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for badarg in OTHERSTUFF:
17560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t1 == badarg, False)
17570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t1 != badarg, True)
17580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(badarg == t1, False)
17590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(badarg != t1, True)
17600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 <= badarg)
17620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 < badarg)
17630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 > badarg)
17640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: t1 >= badarg)
17650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg <= t1)
17660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg < t1)
17670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg > t1)
17680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, lambda: badarg >= t1)
17690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_bad_constructor_arguments(self):
17710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad hours
17720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(0, 0)    # no exception
17730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(23, 0)   # no exception
17740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, -1, 0)
17750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 24, 0)
17760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad minutes
17770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(23, 0)    # no exception
17780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(23, 59)   # no exception
17790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 23, -1)
17800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 23, 60)
17810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad seconds
17820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(23, 59, 0)    # no exception
17830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(23, 59, 59)   # no exception
17840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 23, 59, -1)
17850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 23, 59, 60)
17860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # bad microseconds
17870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(23, 59, 59, 0)        # no exception
17880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.theclass(23, 59, 59, 999999)   # no exception
17890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 23, 59, 59, -1)
17900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, self.theclass, 23, 59, 59, 1000000)
17910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_hash_equality(self):
17930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.theclass(23, 30, 17)
17940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e = self.theclass(23, 30, 17)
17950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d, e)
17960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(d), hash(e))
17970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
17980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic = {d: 1}
17990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic[e] = 2
18000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(dic), 1)
18010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[d], 2)
18020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[e], 2)
18030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = self.theclass(0,  5, 17)
18050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        e = self.theclass(0,  5, 17)
18060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(d, e)
18070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(d), hash(e))
18080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic = {d: 1}
18100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dic[e] = 2
18110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(len(dic), 1)
18120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[d], 2)
18130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dic[e], 2)
18140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_isoformat(self):
18160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(4, 5, 1, 123)
18170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), "04:05:01.000123")
18180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), str(t))
18190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass()
18210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), "00:00:00")
18220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), str(t))
18230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(microsecond=1)
18250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), "00:00:00.000001")
18260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), str(t))
18270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(microsecond=10)
18290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), "00:00:00.000010")
18300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), str(t))
18310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(microsecond=100)
18330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), "00:00:00.000100")
18340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), str(t))
18350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(microsecond=1000)
18370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), "00:00:00.001000")
18380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), str(t))
18390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(microsecond=10000)
18410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), "00:00:00.010000")
18420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), str(t))
18430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(microsecond=100000)
18450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), "00:00:00.100000")
18460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.isoformat(), str(t))
18470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_1653736(self):
18490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # verify it doesn't accept extra keyword arguments
18500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(second=1)
18510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t.isoformat, foo=3)
18520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_strftime(self):
18540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(1, 2, 3, 4)
18550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.strftime('%H %M %S %f'), "01 02 03 000004")
18560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # A naive object replaces %z and %Z with empty strings.
18570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
18580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_format(self):
18600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(1, 2, 3, 4)
18610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.__format__(''), str(t))
18620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # check that a derived class's __str__() gets called
18640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class A(self.theclass):
18650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __str__(self):
18660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return 'A'
18670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        a = A(1, 2, 3, 4)
18680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(a.__format__(''), 'A')
18690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # check that a derived class's strftime gets called
18710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class B(self.theclass):
18720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def strftime(self, format_spec):
18730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return 'B'
18740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = B(1, 2, 3, 4)
18750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(b.__format__(''), str(t))
18760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for fmt in ['%H %M %S',
18780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    ]:
18790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(t.__format__(fmt), t.strftime(fmt))
18800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(a.__format__(fmt), t.strftime(fmt))
18810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(b.__format__(fmt), 'B')
18820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_str(self):
18840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(self.theclass(1, 2, 3, 4)), "01:02:03.000004")
18850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(self.theclass(10, 2, 3, 4000)), "10:02:03.004000")
18860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(self.theclass(0, 2, 3, 400000)), "00:02:03.400000")
18870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(self.theclass(12, 2, 3, 0)), "12:02:03")
18880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(self.theclass(23, 15, 0, 0)), "23:15:00")
18890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
18900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_repr(self):
18910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        name = 'datetime.' + self.theclass.__name__
18920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(self.theclass(1, 2, 3, 4)),
18930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         "%s(1, 2, 3, 4)" % name)
18940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(self.theclass(10, 2, 3, 4000)),
18950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         "%s(10, 2, 3, 4000)" % name)
18960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(self.theclass(0, 2, 3, 400000)),
18970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         "%s(0, 2, 3, 400000)" % name)
18980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(self.theclass(12, 2, 3, 0)),
18990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         "%s(12, 2, 3)" % name)
19000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(self.theclass(23, 15, 0, 0)),
19010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                         "%s(23, 15)" % name)
19020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_resolution_info(self):
19040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(self.theclass.min, self.theclass)
19050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(self.theclass.max, self.theclass)
19060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertIsInstance(self.theclass.resolution, timedelta)
19070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(self.theclass.max > self.theclass.min)
19080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling(self):
19100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 20, 59, 16, 64**2
19110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = self.theclass(*args)
19120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
19130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
19140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
19150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
19160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling_subclass_time(self):
19180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 20, 59, 16, 64**2
19190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = SubclassTime(*args)
19200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
19210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
19220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
19230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
19240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_bool(self):
19260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
19270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(cls(1))
19280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(cls(0, 1))
19290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(cls(0, 0, 1))
19300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(cls(0, 0, 0, 1))
19310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not cls(0))
19320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not cls())
19330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_replace(self):
19350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
19360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = [1, 2, 3, 4]
19370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(*args)
19380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(base, base.replace())
19390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        i = 0
19410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for name, newval in (("hour", 5),
19420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("minute", 6),
19430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("second", 7),
19440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("microsecond", 8)):
19450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs = args[:]
19460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs[i] = newval
19470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            expected = cls(*newargs)
19480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = base.replace(**{name: newval})
19490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
19500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            i += 1
19510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Out of bounds.
19530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(1)
19540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, hour=24)
19550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, minute=-1)
19560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, second=100)
19570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, microsecond=1000000)
19580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_subclass_time(self):
19600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class C(self.theclass):
19620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            theAnswer = 42
19630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __new__(cls, *args, **kws):
19650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                temp = kws.copy()
19660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                extra = temp.pop('extra')
19670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                result = self.theclass.__new__(cls, *args, **temp)
19680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                result.extra = extra
19690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return result
19700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def newmeth(self, start):
19720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return start + self.hour + self.second
19730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 4, 5, 6
19750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt1 = self.theclass(*args)
19770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = C(*args, **{'extra': 7})
19780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.__class__, C)
19800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.theAnswer, 42)
19810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.extra, 7)
19820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt1.isoformat(), dt2.isoformat())
19830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.second - 7)
19840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_backdoor_resistance(self):
19860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # see TestDate.test_backdoor_resistance().
19870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = '2:59.0'
19880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for hour_byte in ' ', '9', chr(24), '\xff':
19890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertRaises(TypeError, self.theclass,
19900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                         hour_byte + base[1:])
19910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# A mixin for classes with a tzinfo= argument.  Subclasses must define
19930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# theclass as a class atribute, and theclass(1, 1, 1, tzinfo=whatever)
19940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# must be legit (which is true for time and datetime).
19950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TZInfoBase:
19960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
19970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_argument_passing(self):
19980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
19990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # A datetime passes itself on, a time passes None.
20000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class introspective(tzinfo):
20010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def tzname(self, dt):    return dt and "real" or "none"
20020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt):
20030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return timedelta(minutes = dt and 42 or -42)
20040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            dst = utcoffset
20050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        obj = cls(1, 2, 3, tzinfo=introspective())
20070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = cls is time and "none" or "real"
20090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(obj.tzname(), expected)
20100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = timedelta(minutes=(cls is time and -42 or 42))
20120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(obj.utcoffset(), expected)
20130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(obj.dst(), expected)
20140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_bad_tzinfo_classes(self):
20160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
20170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, cls, 1, 1, 1, tzinfo=12)
20180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class NiceTry(object):
20200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __init__(self): pass
20210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): pass
20220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, cls, 1, 1, 1, tzinfo=NiceTry)
20230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class BetterTry(tzinfo):
20250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __init__(self): pass
20260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): pass
20270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        b = BetterTry()
20280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(1, 1, 1, tzinfo=b)
20290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t.tzinfo is b)
20300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_utc_offset_out_of_bounds(self):
20320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class Edgy(tzinfo):
20330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __init__(self, offset):
20340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.offset = timedelta(minutes=offset)
20350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt):
20360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return self.offset
20370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
20390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for offset, legit in ((-1440, False),
20400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                              (-1439, True),
20410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                              (1439, True),
20420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                              (1440, False)):
20430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if cls is time:
20440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                t = cls(1, 2, 3, tzinfo=Edgy(offset))
20450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            elif cls is datetime:
20460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                t = cls(6, 6, 6, 1, 2, 3, tzinfo=Edgy(offset))
20470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
20480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                assert 0, "impossible"
20490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if legit:
20500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                aofs = abs(offset)
20510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                h, m = divmod(aofs, 60)
20520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                tag = "%c%02d:%02d" % (offset < 0 and '-' or '+', h, m)
20530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if isinstance(t, datetime):
20540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    t = t.timetz()
20550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(str(t), "01:02:03" + tag)
20560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            else:
20570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertRaises(ValueError, str, t)
20580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_tzinfo_classes(self):
20600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
20610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class C1(tzinfo):
20620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): return None
20630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt): return None
20640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def tzname(self, dt): return None
20650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for t in (cls(1, 1, 1),
20660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                  cls(1, 1, 1, tzinfo=None),
20670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                  cls(1, 1, 1, tzinfo=C1())):
20680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t.utcoffset() is None)
20690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t.dst() is None)
20700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(t.tzname() is None)
20710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class C3(tzinfo):
20730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): return timedelta(minutes=-1439)
20740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt): return timedelta(minutes=1439)
20750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def tzname(self, dt): return "aname"
20760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(1, 1, 1, tzinfo=C3())
20770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.utcoffset(), timedelta(minutes=-1439))
20780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.dst(), timedelta(minutes=1439))
20790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tzname(), "aname")
20800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Wrong types.
20820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class C4(tzinfo):
20830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): return "aname"
20840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt): return 7
20850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def tzname(self, dt): return 0
20860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(1, 1, 1, tzinfo=C4())
20870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t.utcoffset)
20880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t.dst)
20890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t.tzname)
20900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Offset out of range.
20920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class C6(tzinfo):
20930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): return timedelta(hours=-24)
20940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt): return timedelta(hours=24)
20950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(1, 1, 1, tzinfo=C6())
20960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, t.utcoffset)
20970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, t.dst)
20980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
20990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Not a whole number of minutes.
21000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class C7(tzinfo):
21010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): return timedelta(seconds=61)
21020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt): return timedelta(microseconds=-81)
21030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(1, 1, 1, tzinfo=C7())
21040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, t.utcoffset)
21050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, t.dst)
21060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_aware_compare(self):
21080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
21090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure that utcoffset() gets ignored if the comparands have
21110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # the same tzinfo member.
21120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class OperandDependentOffset(tzinfo):
21130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, t):
21140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if t.minute < 10:
21150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    # d0 and d1 equal after adjustment
21160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    return timedelta(minutes=t.minute)
21170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                else:
21180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    # d2 off in the weeds
21190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    return timedelta(minutes=59)
21200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(8, 9, 10, tzinfo=OperandDependentOffset())
21220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d0 = base.replace(minute=3)
21230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d1 = base.replace(minute=9)
21240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d2 = base.replace(minute=11)
21250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for x in d0, d1, d2:
21260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for y in d0, d1, d2:
21270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                got = cmp(x, y)
21280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                expected = cmp(x.minute, y.minute)
21290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(got, expected)
21300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # However, if they're different members, uctoffset is not ignored.
21320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Note that a time can't actually have an operand-depedent offset,
21330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # though (and time.utcoffset() passes None to tzinfo.utcoffset()),
21340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # so skip this test for time.
21350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if cls is not time:
21360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d0 = base.replace(minute=3, tzinfo=OperandDependentOffset())
21370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d1 = base.replace(minute=9, tzinfo=OperandDependentOffset())
21380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d2 = base.replace(minute=11, tzinfo=OperandDependentOffset())
21390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for x in d0, d1, d2:
21400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                for y in d0, d1, d2:
21410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    got = cmp(x, y)
21420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    if (x is d0 or x is d1) and (y is d0 or y is d1):
21430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        expected = 0
21440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    elif x is y is d2:
21450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        expected = 0
21460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    elif x is d2:
21470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        expected = -1
21480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    else:
21490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        assert y is d2
21500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        expected = 1
21510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    self.assertEqual(got, expected)
21520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Testing time objects with a non-None tzinfo.
21550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase):
21560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    theclass = time
21570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_empty(self):
21590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass()
21600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.hour, 0)
21610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.minute, 0)
21620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.second, 0)
21630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.microsecond, 0)
21640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t.tzinfo is None)
21650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_zones(self):
21670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        est = FixedOffset(-300, "EST", 1)
21680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        utc = FixedOffset(0, "UTC", -2)
21690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        met = FixedOffset(60, "MET", 3)
21700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = time( 7, 47, tzinfo=est)
21710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = time(12, 47, tzinfo=utc)
21720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t3 = time(13, 47, tzinfo=met)
21730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t4 = time(microsecond=40)
21740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t5 = time(microsecond=40, tzinfo=utc)
21750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.tzinfo, est)
21770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.tzinfo, utc)
21780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.tzinfo, met)
21790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t4.tzinfo is None)
21800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t5.tzinfo, utc)
21810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.utcoffset(), timedelta(minutes=-300))
21830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.utcoffset(), timedelta(minutes=0))
21840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.utcoffset(), timedelta(minutes=60))
21850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t4.utcoffset() is None)
21860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t1.utcoffset, "no args")
21870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.tzname(), "EST")
21890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.tzname(), "UTC")
21900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.tzname(), "MET")
21910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t4.tzname() is None)
21920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t1.tzname, "no args")
21930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
21940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.dst(), timedelta(minutes=1))
21950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.dst(), timedelta(minutes=-2))
21960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.dst(), timedelta(minutes=3))
21970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t4.dst() is None)
21980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t1.dst, "no args")
21990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(t1), hash(t2))
22010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(t1), hash(t3))
22020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(t2), hash(t3))
22030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
22050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t3)
22060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2, t3)
22070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: t4 == t5) # mixed tz-aware & naive
22080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: t4 < t5) # mixed tz-aware & naive
22090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: t5 < t4) # mixed tz-aware & naive
22100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t1), "07:47:00-05:00")
22120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t2), "12:47:00+00:00")
22130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t3), "13:47:00+01:00")
22140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t4), "00:00:00.000040")
22150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t5), "00:00:00.000040+00:00")
22160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.isoformat(), "07:47:00-05:00")
22180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.isoformat(), "12:47:00+00:00")
22190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.isoformat(), "13:47:00+01:00")
22200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t4.isoformat(), "00:00:00.000040")
22210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t5.isoformat(), "00:00:00.000040+00:00")
22220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = 'datetime.time'
22240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(t1), d + "(7, 47, tzinfo=est)")
22250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(t2), d + "(12, 47, tzinfo=utc)")
22260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(t3), d + "(13, 47, tzinfo=met)")
22270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(t4), d + "(0, 0, 0, 40)")
22280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(t5), d + "(0, 0, 0, 40, tzinfo=utc)")
22290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.strftime("%H:%M:%S %%Z=%Z %%z=%z"),
22310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                     "07:47:00 %Z=EST %z=-0500")
22320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.strftime("%H:%M:%S %Z %z"), "12:47:00 UTC +0000")
22330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.strftime("%H:%M:%S %Z %z"), "13:47:00 MET +0100")
22340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        yuck = FixedOffset(-1439, "%z %Z %%z%%Z")
22360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = time(23, 59, tzinfo=yuck)
22370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.strftime("%H:%M %%Z='%Z' %%z='%z'"),
22380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                     "23:59 %Z='%z %Z %%z%%Z' %z='-2359'")
22390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Check that an invalid tzname result raises an exception.
22410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class Badtzname(tzinfo):
22420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def tzname(self, dt): return 42
22430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = time(2, 3, 4, tzinfo=Badtzname())
22440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.strftime("%H:%M:%S"), "02:03:04")
22450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, t.strftime, "%Z")
22460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_hash_edge_cases(self):
22480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Offsets that overflow a basic time.
22490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(0, 1, 2, 3, tzinfo=FixedOffset(1439, ""))
22500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass(0, 0, 2, 3, tzinfo=FixedOffset(1438, ""))
22510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(t1), hash(t2))
22520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(23, 58, 6, 100, tzinfo=FixedOffset(-1000, ""))
22540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass(23, 48, 6, 100, tzinfo=FixedOffset(-1010, ""))
22550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(t1), hash(t2))
22560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling(self):
22580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try one without a tzinfo.
22590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 20, 59, 16, 64**2
22600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = self.theclass(*args)
22610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
22620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
22630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
22640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
22650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try one with a tzinfo.
22670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tinfo = PicklableFixedOffset(-300, 'cookie')
22680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = self.theclass(5, 6, 7, tzinfo=tinfo)
22690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
22700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
22710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
22720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
22730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertIsInstance(derived.tzinfo, PicklableFixedOffset)
22740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(derived.utcoffset(), timedelta(minutes=-300))
22750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(derived.tzname(), 'cookie')
22760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_more_bool(self):
22780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Test cases with non-None tzinfo.
22790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
22800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(0, tzinfo=FixedOffset(-300, ""))
22820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t)
22830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(5, tzinfo=FixedOffset(-300, ""))
22850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t)
22860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(5, tzinfo=FixedOffset(300, ""))
22880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t)
22890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(23, 59, tzinfo=FixedOffset(23*60 + 59, ""))
22910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not t)
22920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Mostly ensuring this doesn't overflow internally.
22940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(0, tzinfo=FixedOffset(23*60 + 59, ""))
22950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t)
22960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
22970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # But this should yield a value error -- the utcoffset is bogus.
22980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(0, tzinfo=FixedOffset(24*60, ""))
22990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, lambda: bool(t))
23000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Likewise.
23020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = cls(0, tzinfo=FixedOffset(-24*60, ""))
23030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, lambda: bool(t))
23040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_replace(self):
23060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
23070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        z100 = FixedOffset(100, "+100")
23080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        zm200 = FixedOffset(timedelta(minutes=-200), "-200")
23090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = [1, 2, 3, 4, z100]
23100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(*args)
23110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(base, base.replace())
23120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        i = 0
23140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for name, newval in (("hour", 5),
23150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("minute", 6),
23160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("second", 7),
23170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("microsecond", 8),
23180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("tzinfo", zm200)):
23190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs = args[:]
23200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs[i] = newval
23210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            expected = cls(*newargs)
23220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = base.replace(**{name: newval})
23230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
23240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            i += 1
23250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure we can get rid of a tzinfo.
23270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(base.tzname(), "+100")
23280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base2 = base.replace(tzinfo=None)
23290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(base2.tzinfo is None)
23300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(base2.tzname() is None)
23310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure we can add one.
23330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base3 = base2.replace(tzinfo=z100)
23340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(base, base3)
23350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(base.tzinfo is base3.tzinfo)
23360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Out of bounds.
23380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(1)
23390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, hour=24)
23400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, minute=-1)
23410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, second=100)
23420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, microsecond=1000000)
23430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_mixed_compare(self):
23450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = time(1, 2, 3)
23460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = time(1, 2, 3)
23470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
23480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = t2.replace(tzinfo=None)
23490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
23500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = t2.replace(tzinfo=FixedOffset(None, ""))
23510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
23520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = t2.replace(tzinfo=FixedOffset(0, ""))
23530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: t1 == t2)
23540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # In time w/ identical tzinfo objects, utcoffset is ignored.
23560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class Varies(tzinfo):
23570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __init__(self):
23580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.offset = timedelta(minutes=22)
23590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, t):
23600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.offset += timedelta(minutes=1)
23610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return self.offset
23620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        v = Varies()
23640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = t2.replace(tzinfo=v)
23650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = t2.replace(tzinfo=v)
23660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.utcoffset(), timedelta(minutes=23))
23670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.utcoffset(), timedelta(minutes=24))
23680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
23690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # But if they're not identical, it isn't ignored.
23710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = t2.replace(tzinfo=Varies())
23720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 < t2)  # t1's offset counter still going up
23730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_subclass_timetz(self):
23750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class C(self.theclass):
23770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            theAnswer = 42
23780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __new__(cls, *args, **kws):
23800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                temp = kws.copy()
23810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                extra = temp.pop('extra')
23820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                result = self.theclass.__new__(cls, *args, **temp)
23830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                result.extra = extra
23840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return result
23850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def newmeth(self, start):
23870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return start + self.hour + self.second
23880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 4, 5, 6, 500, FixedOffset(-300, "EST", 1)
23900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt1 = self.theclass(*args)
23920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = C(*args, **{'extra': 7})
23930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
23940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.__class__, C)
23950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.theAnswer, 42)
23960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.extra, 7)
23970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt1.utcoffset(), dt2.utcoffset())
23980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.second - 7)
23990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Testing datetime objects with a non-None tzinfo.
24020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestDateTimeTZ(TestDateTime, TZInfoBase, unittest.TestCase):
24040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    theclass = datetime
24050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_trivial(self):
24070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = self.theclass(1, 2, 3, 4, 5, 6, 7)
24080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.year, 1)
24090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.month, 2)
24100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.day, 3)
24110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.hour, 4)
24120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.minute, 5)
24130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.second, 6)
24140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.microsecond, 7)
24150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.tzinfo, None)
24160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_even_more_compare(self):
24180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # The test_compare() and test_more_compare() inherited from TestDate
24190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # and TestDateTime covered non-tzinfo cases.
24200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Smallest possible after UTC adjustment.
24220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(1, 1, 1, tzinfo=FixedOffset(1439, ""))
24230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Largest possible after UTC adjustment.
24240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999999,
24250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           tzinfo=FixedOffset(-1439, ""))
24260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Make sure those compare correctly, and w/o overflow.
24280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 < t2)
24290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 != t2)
24300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t2 > t1)
24310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 == t1)
24330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t2 == t2)
24340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Equal afer adjustment.
24360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(1, ""))
24370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass(2, 1, 1, 3, 13, tzinfo=FixedOffset(3*60+13+2, ""))
24380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
24390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Change t1 not to subtract a minute, and t1 should be larger.
24410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(0, ""))
24420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 > t2)
24430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Change t1 to subtract 2 minutes, and t1 should be smaller.
24450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(2, ""))
24460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 < t2)
24470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Back to the original t1, but make seconds resolve it.
24490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(1, ""),
24500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           second=1)
24510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 > t2)
24520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Likewise, but make microseconds resolve it.
24540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(1, ""),
24550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                           microsecond=1)
24560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 > t2)
24570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Make t2 naive and it should fail.
24590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass.min
24600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: t1 == t2)
24610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2, t2)
24620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # It's also naive if it has tzinfo but tzinfo.utcoffset() is None.
24640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class Naive(tzinfo):
24650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): return None
24660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass(5, 6, 7, tzinfo=Naive())
24670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: t1 == t2)
24680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2, t2)
24690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # OTOH, it's OK to compare two of these mixing the two ways of being
24710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # naive.
24720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(5, 6, 7)
24730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
24740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try a bogus uctoffset.
24760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class Bogus(tzinfo):
24770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt):
24780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return timedelta(minutes=1440) # out of bounds
24790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = self.theclass(2, 2, 2, tzinfo=Bogus())
24800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = self.theclass(2, 2, 2, tzinfo=FixedOffset(0, ""))
24810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, lambda: t1 == t2)
24820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_pickling(self):
24840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try one without a tzinfo.
24850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 6, 7, 23, 20, 59, 1, 64**2
24860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = self.theclass(*args)
24870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
24880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
24890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
24900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
24910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
24920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try one with a tzinfo.
24930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tinfo = PicklableFixedOffset(-300, 'cookie')
24940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        orig = self.theclass(*args, **{'tzinfo': tinfo})
24950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        derived = self.theclass(1, 1, 1, tzinfo=FixedOffset(0, "", 0))
24960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for pickler, unpickler, proto in pickle_choices:
24970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            green = pickler.dumps(orig, proto)
24980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            derived = unpickler.loads(green)
24990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(orig, derived)
25000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertIsInstance(derived.tzinfo, PicklableFixedOffset)
25010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(derived.utcoffset(), timedelta(minutes=-300))
25020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(derived.tzname(), 'cookie')
25030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_extreme_hashes(self):
25050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # If an attempt is made to hash these via subtracting the offset
25060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # then hashing a datetime object, OverflowError results.  The
25070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Python implementation used to blow up here.
25080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(1, 1, 1, tzinfo=FixedOffset(1439, ""))
25090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        hash(t)
25100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999999,
25110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          tzinfo=FixedOffset(-1439, ""))
25120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        hash(t)
25130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # OTOH, an OOB offset should blow up.
25150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = self.theclass(5, 5, 5, tzinfo=FixedOffset(-1440, ""))
25160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, hash, t)
25170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_zones(self):
25190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        est = FixedOffset(-300, "EST")
25200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        utc = FixedOffset(0, "UTC")
25210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        met = FixedOffset(60, "MET")
25220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = datetime(2002, 3, 19,  7, 47, tzinfo=est)
25230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = datetime(2002, 3, 19, 12, 47, tzinfo=utc)
25240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t3 = datetime(2002, 3, 19, 13, 47, tzinfo=met)
25250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.tzinfo, est)
25260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.tzinfo, utc)
25270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.tzinfo, met)
25280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.utcoffset(), timedelta(minutes=-300))
25290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.utcoffset(), timedelta(minutes=0))
25300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.utcoffset(), timedelta(minutes=60))
25310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.tzname(), "EST")
25320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.tzname(), "UTC")
25330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t3.tzname(), "MET")
25340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(t1), hash(t2))
25350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(t1), hash(t3))
25360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(hash(t2), hash(t3))
25370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
25380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t3)
25390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2, t3)
25400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t1), "2002-03-19 07:47:00-05:00")
25410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t2), "2002-03-19 12:47:00+00:00")
25420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(str(t3), "2002-03-19 13:47:00+01:00")
25430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = 'datetime.datetime(2002, 3, 19, '
25440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(t1), d + "7, 47, tzinfo=est)")
25450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(t2), d + "12, 47, tzinfo=utc)")
25460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(repr(t3), d + "13, 47, tzinfo=met)")
25470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_combine(self):
25490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        met = FixedOffset(60, "MET")
25500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d = date(2002, 3, 4)
25510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tz = time(18, 45, 3, 1234, tzinfo=met)
25520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = datetime.combine(d, tz)
25530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt, datetime(2002, 3, 4, 18, 45, 3, 1234,
25540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                        tzinfo=met))
25550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_extract(self):
25570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        met = FixedOffset(60, "MET")
25580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = self.theclass(2002, 3, 4, 18, 45, 3, 1234, tzinfo=met)
25590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.date(), date(2002, 3, 4))
25600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.time(), time(18, 45, 3, 1234))
25610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.timetz(), time(18, 45, 3, 1234, tzinfo=met))
25620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_tz_aware_arithmetic(self):
25640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import random
25650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        now = self.theclass.now()
25670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tz55 = FixedOffset(-330, "west 5:30")
25680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        timeaware = now.time().replace(tzinfo=tz55)
25690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nowaware = self.theclass.combine(now.date(), timeaware)
25700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(nowaware.tzinfo is tz55)
25710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(nowaware.timetz(), timeaware)
25720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Can't mix aware and non-aware.
25740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: now - nowaware)
25750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: nowaware - now)
25760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # And adding datetime's doesn't make sense, aware or not.
25780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: now + nowaware)
25790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: nowaware + now)
25800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: nowaware + nowaware)
25810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Subtracting should yield 0.
25830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(now - now, timedelta(0))
25840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(nowaware - nowaware, timedelta(0))
25850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Adding a delta should preserve tzinfo.
25870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        delta = timedelta(weeks=1, minutes=12, microseconds=5678)
25880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nowawareplus = nowaware + delta
25890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(nowaware.tzinfo is tz55)
25900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nowawareplus2 = delta + nowaware
25910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(nowawareplus2.tzinfo is tz55)
25920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(nowawareplus, nowawareplus2)
25930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
25940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # that - delta should be what we started with, and that - what we
25950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # started with should be delta.
25960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        diff = nowawareplus - delta
25970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(diff.tzinfo is tz55)
25980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(nowaware, diff)
25990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: delta - nowawareplus)
26000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(nowawareplus - nowaware, delta)
26010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
26020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Make up a random timezone.
26030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tzr = FixedOffset(random.randrange(-1439, 1440), "randomtimezone")
26040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Attach it to nowawareplus.
26050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nowawareplus = nowawareplus.replace(tzinfo=tzr)
26060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(nowawareplus.tzinfo is tzr)
26070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Make sure the difference takes the timezone adjustments into account.
26080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        got = nowaware - nowawareplus
26090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Expected:  (nowaware base - nowaware offset) -
26100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #            (nowawareplus base - nowawareplus offset) =
26110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #            (nowaware base - nowawareplus base) +
26120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #            (nowawareplus offset - nowaware offset) =
26130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #            -delta + nowawareplus offset - nowaware offset
26140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = nowawareplus.utcoffset() - nowaware.utcoffset() - delta
26150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(got, expected)
26160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
26170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try max possible difference.
26180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        min = self.theclass(1, 1, 1, tzinfo=FixedOffset(1439, "min"))
26190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        max = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999999,
26200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                            tzinfo=FixedOffset(-1439, "max"))
26210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        maxdiff = max - min
26220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(maxdiff, self.theclass.max - self.theclass.min +
26230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                  timedelta(minutes=2*1439))
26240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
26250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_tzinfo_now(self):
26260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        meth = self.theclass.now
26270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up).
26280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = meth()
26290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try with and without naming the keyword.
26300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        off42 = FixedOffset(42, "42")
26310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        another = meth(off42)
26320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        again = meth(tz=off42)
26330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(another.tzinfo is again.tzinfo)
26340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(another.utcoffset(), timedelta(minutes=42))
26350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Bad argument with and w/o naming the keyword.
26360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, 16)
26370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, tzinfo=16)
26380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Bad keyword name.
26390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, tinfo=off42)
26400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Too many args.
26410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, off42, off42)
26420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
26430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # We don't know which time zone we're in, and don't have a tzinfo
26440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # class to represent it, so seeing whether a tz argument actually
26450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # does a conversion is tricky.
26460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        weirdtz = FixedOffset(timedelta(hours=15, minutes=58), "weirdtz", 0)
26470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        utc = FixedOffset(0, "utc", 0)
26480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for dummy in range(3):
26490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            now = datetime.now(weirdtz)
26500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertTrue(now.tzinfo is weirdtz)
26510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            utcnow = datetime.utcnow().replace(tzinfo=utc)
26520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            now2 = utcnow.astimezone(weirdtz)
26530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if abs(now - now2) < timedelta(seconds=30):
26540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                break
26550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Else the code is broken, or more than 30 seconds passed between
26560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # calls; assuming the latter, just try again.
26570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
26580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Three strikes and we're out.
26590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.fail("utcnow(), now(tz), or astimezone() may be broken")
26600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
26610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_tzinfo_fromtimestamp(self):
26620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import time
26630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        meth = self.theclass.fromtimestamp
26640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        ts = time.time()
26650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up).
26660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = meth(ts)
26670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try with and without naming the keyword.
26680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        off42 = FixedOffset(42, "42")
26690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        another = meth(ts, off42)
26700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        again = meth(ts, tz=off42)
26710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(another.tzinfo is again.tzinfo)
26720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(another.utcoffset(), timedelta(minutes=42))
26730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Bad argument with and w/o naming the keyword.
26740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, ts, 16)
26750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, ts, tzinfo=16)
26760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Bad keyword name.
26770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, ts, tinfo=off42)
26780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Too many args.
26790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, ts, off42, off42)
26800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Too few args.
26810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth)
26820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
26830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try to make sure tz= actually does some conversion.
26840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        timestamp = 1000000000
26850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        utcdatetime = datetime.utcfromtimestamp(timestamp)
26860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # In POSIX (epoch 1970), that's 2001-09-09 01:46:40 UTC, give or take.
26870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # But on some flavor of Mac, it's nowhere near that.  So we can't have
26880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # any idea here what time that actually is, we can only test that
26890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # relative changes match.
26900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        utcoffset = timedelta(hours=-15, minutes=39) # arbitrary, but not zero
26910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tz = FixedOffset(utcoffset, "tz", 0)
26920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = utcdatetime + utcoffset
26930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        got = datetime.fromtimestamp(timestamp, tz)
26940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(expected, got.replace(tzinfo=None))
26950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
26960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_tzinfo_utcnow(self):
26970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        meth = self.theclass.utcnow
26980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up).
26990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = meth()
27000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try with and without naming the keyword; for whatever reason,
27010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # utcnow() doesn't accept a tzinfo argument.
27020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        off42 = FixedOffset(42, "42")
27030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, off42)
27040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, tzinfo=off42)
27050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_tzinfo_utcfromtimestamp(self):
27070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        import time
27080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        meth = self.theclass.utcfromtimestamp
27090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        ts = time.time()
27100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up).
27110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = meth(ts)
27120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Try with and without naming the keyword; for whatever reason,
27130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # utcfromtimestamp() doesn't accept a tzinfo argument.
27140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        off42 = FixedOffset(42, "42")
27150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, ts, off42)
27160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, meth, ts, tzinfo=off42)
27170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_tzinfo_timetuple(self):
27190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # TestDateTime tested most of this.  datetime adds a twist to the
27200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # DST flag.
27210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class DST(tzinfo):
27220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __init__(self, dstvalue):
27230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if isinstance(dstvalue, int):
27240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    dstvalue = timedelta(minutes=dstvalue)
27250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.dstvalue = dstvalue
27260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt):
27270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return self.dstvalue
27280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
27300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for dstvalue, flag in (-33, 1), (33, 1), (0, 0), (None, -1):
27310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = cls(1, 1, 1, 10, 20, 30, 40, tzinfo=DST(dstvalue))
27320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            t = d.timetuple()
27330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(1, t.tm_year)
27340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(1, t.tm_mon)
27350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(1, t.tm_mday)
27360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(10, t.tm_hour)
27370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(20, t.tm_min)
27380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(30, t.tm_sec)
27390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(0, t.tm_wday)
27400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(1, t.tm_yday)
27410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(flag, t.tm_isdst)
27420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # dst() returns wrong type.
27440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, cls(1, 1, 1, tzinfo=DST("x")).timetuple)
27450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # dst() at the edge.
27470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cls(1,1,1, tzinfo=DST(1439)).timetuple().tm_isdst, 1)
27480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(cls(1,1,1, tzinfo=DST(-1439)).timetuple().tm_isdst, 1)
27490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # dst() out of range.
27510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, cls(1,1,1, tzinfo=DST(1440)).timetuple)
27520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, cls(1,1,1, tzinfo=DST(-1440)).timetuple)
27530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_utctimetuple(self):
27550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class DST(tzinfo):
27560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __init__(self, dstvalue):
27570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if isinstance(dstvalue, int):
27580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    dstvalue = timedelta(minutes=dstvalue)
27590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.dstvalue = dstvalue
27600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt):
27610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return self.dstvalue
27620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
27640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # This can't work:  DST didn't implement utcoffset.
27650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(NotImplementedError,
27660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                          cls(1, 1, 1, tzinfo=DST(0)).utcoffset)
27670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class UOFS(DST):
27690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __init__(self, uofs, dofs=None):
27700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                DST.__init__(self, dofs)
27710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.uofs = timedelta(minutes=uofs)
27720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt):
27730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return self.uofs
27740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure tm_isdst is 0 regardless of what dst() says:  DST is never
27760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # in effect for a UTC time.
27770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for dstvalue in -33, 33, 0, None:
27780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=UOFS(-53, dstvalue))
27790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            t = d.utctimetuple()
27800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.year, t.tm_year)
27810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.month, t.tm_mon)
27820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.day, t.tm_mday)
27830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(11, t.tm_hour) # 20mm + 53mm = 1hn + 13mm
27840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(13, t.tm_min)
27850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.second, t.tm_sec)
27860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.weekday(), t.tm_wday)
27870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(d.toordinal() - date(1, 1, 1).toordinal() + 1,
27880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             t.tm_yday)
27890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(0, t.tm_isdst)
27900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
27910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # At the edges, UTC adjustment can normalize into years out-of-range
27920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # for a datetime object.  Ensure that a correct timetuple is
27930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # created anyway.
27940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        tiny = cls(MINYEAR, 1, 1, 0, 0, 37, tzinfo=UOFS(1439))
27950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # That goes back 1 minute less than a full day.
27960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = tiny.utctimetuple()
27970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_year, MINYEAR-1)
27980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_mon, 12)
27990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_mday, 31)
28000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_hour, 0)
28010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_min, 1)
28020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_sec, 37)
28030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_yday, 366)    # "year 0" is a leap year
28040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_isdst, 0)
28050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        huge = cls(MAXYEAR, 12, 31, 23, 59, 37, 999999, tzinfo=UOFS(-1439))
28070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # That goes forward 1 minute less than a full day.
28080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t = huge.utctimetuple()
28090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_year, MAXYEAR+1)
28100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_mon, 1)
28110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_mday, 1)
28120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_hour, 23)
28130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_min, 58)
28140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_sec, 37)
28150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_yday, 1)
28160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t.tm_isdst, 0)
28170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_tzinfo_isoformat(self):
28190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        zero = FixedOffset(0, "+00:00")
28200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        plus = FixedOffset(220, "+03:40")
28210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        minus = FixedOffset(-231, "-03:51")
28220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        unknown = FixedOffset(None, "")
28230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
28250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        datestr = '0001-02-03'
28260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for ofs in None, zero, plus, minus, unknown:
28270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for us in 0, 987001:
28280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                d = cls(1, 2, 3, 4, 5, 59, us, tzinfo=ofs)
28290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                timestr = '04:05:59' + (us and '.987001' or '')
28300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                ofsstr = ofs is not None and d.tzname() or ''
28310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                tailstr = timestr + ofsstr
28320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                iso = d.isoformat()
28330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(iso, datestr + 'T' + tailstr)
28340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(iso, d.isoformat('T'))
28350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(d.isoformat('k'), datestr + 'k' + tailstr)
28360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(str(d), datestr + ' ' + tailstr)
28370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_replace(self):
28390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
28400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        z100 = FixedOffset(100, "+100")
28410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        zm200 = FixedOffset(timedelta(minutes=-200), "-200")
28420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = [1, 2, 3, 4, 5, 6, 7, z100]
28430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(*args)
28440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(base, base.replace())
28450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        i = 0
28470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for name, newval in (("year", 2),
28480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("month", 3),
28490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("day", 4),
28500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("hour", 5),
28510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("minute", 6),
28520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("second", 7),
28530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("microsecond", 8),
28540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             ("tzinfo", zm200)):
28550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs = args[:]
28560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            newargs[i] = newval
28570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            expected = cls(*newargs)
28580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = base.replace(**{name: newval})
28590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
28600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            i += 1
28610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure we can get rid of a tzinfo.
28630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(base.tzname(), "+100")
28640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base2 = base.replace(tzinfo=None)
28650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(base2.tzinfo is None)
28660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(base2.tzname() is None)
28670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure we can add one.
28690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base3 = base2.replace(tzinfo=z100)
28700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(base, base3)
28710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(base.tzinfo is base3.tzinfo)
28720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Out of bounds.
28740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(2000, 2, 29)
28750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, base.replace, year=2001)
28760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_more_astimezone(self):
28780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # The inherited test_astimezone covered some trivial and error cases.
28790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fnone = FixedOffset(None, "None")
28800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        f44m = FixedOffset(44, "44")
28810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fm5h = FixedOffset(-timedelta(hours=5), "m300")
28820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt = self.theclass.now(tz=f44m)
28840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(dt.tzinfo is f44m)
28850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Replacing with degenerate tzinfo raises an exception.
28860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, dt.astimezone, fnone)
28870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ditto with None tz.
28880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, dt.astimezone, None)
28890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Replacing with same tzinfo makes no change.
28900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        x = dt.astimezone(dt.tzinfo)
28910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(x.tzinfo is f44m)
28920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(x.date(), dt.date())
28930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(x.time(), dt.time())
28940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
28950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Replacing with different tzinfo does adjust.
28960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        got = dt.astimezone(fm5h)
28970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(got.tzinfo is fm5h)
28980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(got.utcoffset(), timedelta(hours=-5))
28990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = dt - dt.utcoffset()  # in effect, convert to UTC
29000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected += fm5h.utcoffset(dt)  # and from there to local time
29010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = expected.replace(tzinfo=fm5h) # and attach new tzinfo
29020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(got.date(), expected.date())
29030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(got.time(), expected.time())
29040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(got.timetz(), expected.timetz())
29050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(got.tzinfo is expected.tzinfo)
29060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(got, expected)
29070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_aware_subtract(self):
29090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        cls = self.theclass
29100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ensure that utcoffset() is ignored when the operands have the
29120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # same tzinfo member.
29130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class OperandDependentOffset(tzinfo):
29140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, t):
29150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if t.minute < 10:
29160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    # d0 and d1 equal after adjustment
29170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    return timedelta(minutes=t.minute)
29180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                else:
29190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    # d2 off in the weeds
29200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    return timedelta(minutes=59)
29210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(8, 9, 10, 11, 12, 13, 14, tzinfo=OperandDependentOffset())
29230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d0 = base.replace(minute=3)
29240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d1 = base.replace(minute=9)
29250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d2 = base.replace(minute=11)
29260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for x in d0, d1, d2:
29270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for y in d0, d1, d2:
29280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                got = x - y
29290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                expected = timedelta(minutes=x.minute - y.minute)
29300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(got, expected)
29310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # OTOH, if the tzinfo members are distinct, utcoffsets aren't
29330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # ignored.
29340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        base = cls(8, 9, 10, 11, 12, 13, 14)
29350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d0 = base.replace(minute=3, tzinfo=OperandDependentOffset())
29360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d1 = base.replace(minute=9, tzinfo=OperandDependentOffset())
29370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        d2 = base.replace(minute=11, tzinfo=OperandDependentOffset())
29380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for x in d0, d1, d2:
29390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for y in d0, d1, d2:
29400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                got = x - y
29410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                if (x is d0 or x is d1) and (y is d0 or y is d1):
29420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    expected = timedelta(0)
29430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                elif x is y is d2:
29440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    expected = timedelta(0)
29450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                elif x is d2:
29460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    expected = timedelta(minutes=(11-59)-0)
29470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                else:
29480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    assert y is d2
29490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    expected = timedelta(minutes=0-(11-59))
29500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.assertEqual(got, expected)
29510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_mixed_compare(self):
29530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = datetime(1, 2, 3, 4, 5, 6, 7)
29540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = datetime(1, 2, 3, 4, 5, 6, 7)
29550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
29560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = t2.replace(tzinfo=None)
29570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
29580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = t2.replace(tzinfo=FixedOffset(None, ""))
29590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
29600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = t2.replace(tzinfo=FixedOffset(0, ""))
29610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: t1 == t2)
29620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # In datetime w/ identical tzinfo objects, utcoffset is ignored.
29640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class Varies(tzinfo):
29650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __init__(self):
29660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.offset = timedelta(minutes=22)
29670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, t):
29680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.offset += timedelta(minutes=1)
29690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return self.offset
29700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        v = Varies()
29720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t1 = t2.replace(tzinfo=v)
29730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = t2.replace(tzinfo=v)
29740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1.utcoffset(), timedelta(minutes=23))
29750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t2.utcoffset(), timedelta(minutes=24))
29760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(t1, t2)
29770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # But if they're not identical, it isn't ignored.
29790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        t2 = t2.replace(tzinfo=Varies())
29800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(t1 < t2)  # t1's offset counter still going up
29810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_subclass_datetimetz(self):
29830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class C(self.theclass):
29850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            theAnswer = 42
29860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def __new__(cls, *args, **kws):
29880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                temp = kws.copy()
29890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                extra = temp.pop('extra')
29900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                result = self.theclass.__new__(cls, *args, **temp)
29910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                result.extra = extra
29920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return result
29930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def newmeth(self, start):
29950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return start + self.hour + self.year
29960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        args = 2002, 12, 31, 4, 5, 6, 500, FixedOffset(-300, "EST", 1)
29980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
29990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt1 = self.theclass(*args)
30000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt2 = C(*args, **{'extra': 7})
30010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.__class__, C)
30030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.theAnswer, 42)
30040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.extra, 7)
30050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt1.utcoffset(), dt2.utcoffset())
30060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.year - 7)
30070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Pain to set up DST-aware tzinfo classes.
30090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef first_sunday_on_or_after(dt):
30110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    days_to_go = 6 - dt.weekday()
30120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    if days_to_go:
30130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dt += timedelta(days_to_go)
30140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    return dt
30150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiZERO = timedelta(0)
30170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiHOUR = timedelta(hours=1)
30180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDAY = timedelta(days=1)
30190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# In the US, DST starts at 2am (standard time) on the first Sunday in April.
30200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDSTSTART = datetime(1, 4, 1, 2)
30210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# and ends at 2am (DST time; 1am standard time) on the last Sunday of Oct,
30220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# which is the first Sunday on or after Oct 25.  Because we view 1:MM as
30230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# being standard time on that day, there is no spelling in local time of
30240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# the last hour of DST (that's 1:MM DST, but 1:MM is taken as standard time).
30250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDSTEND = datetime(1, 10, 25, 1)
30260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass USTimeZone(tzinfo):
30280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __init__(self, hours, reprname, stdname, dstname):
30300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.stdoffset = timedelta(hours=hours)
30310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.reprname = reprname
30320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.stdname = stdname
30330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.dstname = dstname
30340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def __repr__(self):
30360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.reprname
30370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def tzname(self, dt):
30390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if self.dst(dt):
30400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self.dstname
30410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
30420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return self.stdname
30430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def utcoffset(self, dt):
30450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        return self.stdoffset + self.dst(dt)
30460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def dst(self, dt):
30480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if dt is None or dt.tzinfo is None:
30490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # An exception instead may be sensible here, in one or more of
30500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # the cases.
30510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return ZERO
30520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        assert dt.tzinfo is self
30530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Find first Sunday in April.
30550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
30560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        assert start.weekday() == 6 and start.month == 4 and start.day <= 7
30570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Find last Sunday in October.
30590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))
30600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        assert end.weekday() == 6 and end.month == 10 and end.day >= 25
30610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Can't compare naive to aware objects, so strip the timezone from
30630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # dt first.
30640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if start <= dt.replace(tzinfo=None) < end:
30650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return HOUR
30660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
30670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            return ZERO
30680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiEastern  = USTimeZone(-5, "Eastern",  "EST", "EDT")
30700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiCentral  = USTimeZone(-6, "Central",  "CST", "CDT")
30710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMountain = USTimeZone(-7, "Mountain", "MST", "MDT")
30720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiPacific  = USTimeZone(-8, "Pacific",  "PST", "PDT")
30730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiutc_real = FixedOffset(0, "UTC", 0)
30740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# For better test coverage, we want another flavor of UTC that's west of
30750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# the Eastern and Pacific timezones.
30760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiutc_fake = FixedOffset(-12*60, "UTCfake", 0)
30770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestTimezoneConversions(unittest.TestCase):
30790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # The DST switch times for 2002, in std time.
30800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    dston = datetime(2002, 4, 7, 2)
30810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    dstoff = datetime(2002, 10, 27, 1)
30820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    theclass = datetime
30840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Check a time that's inside DST.
30860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def checkinside(self, dt, tz, utc, dston, dstoff):
30870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.dst(), HOUR)
30880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Conversion to our own timezone is always an identity.
30900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.astimezone(tz), dt)
30910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        asutc = dt.astimezone(utc)
30930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        there_and_back = asutc.astimezone(tz)
30940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
30950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Conversion to UTC and back isn't always an identity here,
30960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # because there are redundant spellings (in local time) of
30970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # UTC time when DST begins:  the clock jumps from 1:59:59
30980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # to 3:00:00, and a local time of 2:MM:SS doesn't really
30990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # make sense then.  The classes above treat 2:MM:SS as
31000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # daylight time then (it's "after 2am"), really an alias
31010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # for 1:MM:SS standard time.  The latter form is what
31020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # conversion back from UTC produces.
31030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if dt.date() == dston.date() and dt.hour == 2:
31040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # We're in the redundant hour, and coming back from
31050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # UTC gives the 1:MM:SS standard-time spelling.
31060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(there_and_back + HOUR, dt)
31070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Although during was considered to be in daylight
31080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # time, there_and_back is not.
31090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(there_and_back.dst(), ZERO)
31100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # They're the same times in UTC.
31110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(there_and_back.astimezone(utc),
31120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                             dt.astimezone(utc))
31130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
31140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # We're not in the redundant hour.
31150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(dt, there_and_back)
31160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
31170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Because we have a redundant spelling when DST begins, there is
31180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # (unfortunately) an hour when DST ends that can't be spelled at all in
31190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # local time.  When DST ends, the clock jumps from 1:59 back to 1:00
31200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # again.  The hour 1:MM DST has no spelling then:  1:MM is taken to be
31210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # standard time.  1:MM DST == 0:MM EST, but 0:MM is taken to be
31220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # daylight time.  The hour 1:MM daylight == 0:MM standard can't be
31230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # expressed in local time.  Nevertheless, we want conversion back
31240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # from UTC to mimic the local clock's "repeat an hour" behavior.
31250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nexthour_utc = asutc + HOUR
31260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        nexthour_tz = nexthour_utc.astimezone(tz)
31270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        if dt.date() == dstoff.date() and dt.hour == 0:
31280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # We're in the hour before the last DST hour.  The last DST hour
31290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # is ineffable.  We want the conversion back to repeat 1:MM.
31300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(nexthour_tz, dt.replace(hour=1))
31310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            nexthour_utc += HOUR
31320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            nexthour_tz = nexthour_utc.astimezone(tz)
31330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(nexthour_tz, dt.replace(hour=1))
31340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        else:
31350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(nexthour_tz - dt, HOUR)
31360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
31370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    # Check a time that's outside DST.
31380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def checkoutside(self, dt, tz, utc):
31390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.dst(), ZERO)
31400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
31410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Conversion to our own timezone is always an identity.
31420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt.astimezone(tz), dt)
31430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
31440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Converting to UTC and back is an identity too.
31450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        asutc = dt.astimezone(utc)
31460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        there_and_back = asutc.astimezone(tz)
31470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(dt, there_and_back)
31480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
31490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def convert_between_tz_and_utc(self, tz, utc):
31500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dston = self.dston.replace(tzinfo=tz)
31510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Because 1:MM on the day DST ends is taken as being standard time,
31520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # there is no spelling in tz for the last hour of daylight time.
31530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # For purposes of the test, the last hour of DST is 0:MM, which is
31540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # taken as being daylight time (and 1:MM is taken as being standard
31550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # time).
31560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        dstoff = self.dstoff.replace(tzinfo=tz)
31570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for delta in (timedelta(weeks=13),
31580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                      DAY,
31590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                      HOUR,
31600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                      timedelta(minutes=1),
31610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                      timedelta(microseconds=1)):
31620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
31630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.checkinside(dston, tz, utc, dston, dstoff)
31640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for during in dston + delta, dstoff - delta:
31650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.checkinside(during, tz, utc, dston, dstoff)
31660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
31670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.checkoutside(dstoff, tz, utc)
31680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for outside in dston - delta, dstoff + delta:
31690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                self.checkoutside(outside, tz, utc)
31700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
31710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_easy(self):
31720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Despite the name of this test, the endcases are excruciating.
31730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.convert_between_tz_and_utc(Eastern, utc_real)
31740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.convert_between_tz_and_utc(Pacific, utc_real)
31750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.convert_between_tz_and_utc(Eastern, utc_fake)
31760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.convert_between_tz_and_utc(Pacific, utc_fake)
31770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # The next is really dancing near the edge.  It works because
31780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Pacific and Eastern are far enough apart that their "problem
31790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # hours" don't overlap.
31800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.convert_between_tz_and_utc(Eastern, Pacific)
31810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.convert_between_tz_and_utc(Pacific, Eastern)
31820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # OTOH, these fail!  Don't enable them.  The difficulty is that
31830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # the edge case tests assume that every hour is representable in
31840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # the "utc" class.  This is always true for a fixed-offset tzinfo
31850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # class (lke utc_real and utc_fake), but not for Eastern or Central.
31860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # For these adjacent DST-aware time zones, the range of time offsets
31870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # tested ends up creating hours in the one that aren't representable
31880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # in the other.  For the same reason, we would see failures in the
31890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Eastern vs Pacific tests too if we added 3*HOUR to the list of
31900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # offset deltas in convert_between_tz_and_utc().
31910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #
31920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # self.convert_between_tz_and_utc(Eastern, Central)  # can't work
31930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # self.convert_between_tz_and_utc(Central, Eastern)  # can't work
31940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
31950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_tricky(self):
31960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # 22:00 on day before daylight starts.
31970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fourback = self.dston - timedelta(hours=4)
31980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        ninewest = FixedOffset(-9*60, "-0900", 0)
31990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fourback = fourback.replace(tzinfo=ninewest)
32000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # 22:00-0900 is 7:00 UTC == 2:00 EST == 3:00 DST.  Since it's "after
32010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # 2", we should get the 3 spelling.
32020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # If we plug 22:00 the day before into Eastern, it "looks like std
32030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # time", so its offset is returned as -5, and -5 - -9 = 4.  Adding 4
32040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # to 22:00 lands on 2:00, which makes no sense in local time (the
32050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # local clock jumps from 1 to 3).  The point here is to make sure we
32060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # get the 3 spelling.
32070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = self.dston.replace(hour=3)
32080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        got = fourback.astimezone(Eastern).replace(tzinfo=None)
32090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(expected, got)
32100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Similar, but map to 6:00 UTC == 1:00 EST == 2:00 DST.  In that
32120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # case we want the 1:00 spelling.
32130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        sixutc = self.dston.replace(hour=6, tzinfo=utc_real)
32140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Now 6:00 "looks like daylight", so the offset wrt Eastern is -4,
32150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # and adding -4-0 == -4 gives the 2:00 spelling.  We want the 1:00 EST
32160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # spelling.
32170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        expected = self.dston.replace(hour=1)
32180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        got = sixutc.astimezone(Eastern).replace(tzinfo=None)
32190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(expected, got)
32200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Now on the day DST ends, we want "repeat an hour" behavior.
32220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #  UTC  4:MM  5:MM  6:MM  7:MM  checking these
32230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #  EST 23:MM  0:MM  1:MM  2:MM
32240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #  EDT  0:MM  1:MM  2:MM  3:MM
32250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # wall  0:MM  1:MM  1:MM  2:MM  against these
32260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for utc in utc_real, utc_fake:
32270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            for tz in Eastern, Pacific:
32280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                first_std_hour = self.dstoff - timedelta(hours=2) # 23:MM
32290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                # Convert that to UTC.
32300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                first_std_hour -= tz.utcoffset(None)
32310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                # Adjust for possibly fake UTC.
32320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                asutc = first_std_hour + utc.utcoffset(None)
32330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                # First UTC hour to convert; this is 4:00 when utc=utc_real &
32340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                # tz=Eastern.
32350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                asutcbase = asutc.replace(tzinfo=utc)
32360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                for tzhour in (0, 1, 1, 2):
32370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    expectedbase = self.dstoff.replace(hour=tzhour)
32380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    for minute in 0, 30, 59:
32390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        expected = expectedbase.replace(minute=minute)
32400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        asutc = asutcbase.replace(minute=minute)
32410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        astz = asutc.astimezone(tz)
32420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                        self.assertEqual(astz.replace(tzinfo=None), expected)
32430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                    asutcbase += HOUR
32440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_bogus_dst(self):
32470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class ok(tzinfo):
32480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def utcoffset(self, dt): return HOUR
32490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt): return HOUR
32500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        now = self.theclass.now().replace(tzinfo=utc_real)
32520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Doesn't blow up.
32530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        now.astimezone(ok())
32540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Does blow up.
32560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class notok(ok):
32570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def dst(self, dt): return None
32580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, now.astimezone, notok())
32590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_fromutc(self):
32610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, Eastern.fromutc)   # not enough args
32620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        now = datetime.utcnow().replace(tzinfo=utc_real)
32630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(ValueError, Eastern.fromutc, now) # wrong tzinfo
32640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        now = now.replace(tzinfo=Eastern)   # insert correct tzinfo
32650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        enow = Eastern.fromutc(now)         # doesn't blow up
32660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(enow.tzinfo, Eastern) # has right tzinfo member
32670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, Eastern.fromutc, now, now) # too many args
32680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, Eastern.fromutc, date.today()) # wrong type
32690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Always converts UTC to standard time.
32710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        class FauxUSTimeZone(USTimeZone):
32720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            def fromutc(self, dt):
32730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                return dt + self.stdoffset
32740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        FEastern  = FauxUSTimeZone(-5, "FEastern",  "FEST", "FEDT")
32750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #  UTC  4:MM  5:MM  6:MM  7:MM  8:MM  9:MM
32770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #  EST 23:MM  0:MM  1:MM  2:MM  3:MM  4:MM
32780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        #  EDT  0:MM  1:MM  2:MM  3:MM  4:MM  5:MM
32790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Check around DST start.
32810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        start = self.dston.replace(hour=4, tzinfo=Eastern)
32820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fstart = start.replace(tzinfo=FEastern)
32830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for wall in 23, 0, 1, 3, 4, 5:
32840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            expected = start.replace(hour=wall)
32850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            if wall == 23:
32860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                expected -= timedelta(days=1)
32870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = Eastern.fromutc(start)
32880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
32890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            expected = fstart + FEastern.stdoffset
32910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = FEastern.fromutc(fstart)
32920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
32930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Ensure astimezone() calls fromutc() too.
32950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = fstart.replace(tzinfo=utc_real).astimezone(FEastern)
32960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
32970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
32980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            start += HOUR
32990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            fstart += HOUR
33000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Check around DST end.
33020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        start = self.dstoff.replace(hour=4, tzinfo=Eastern)
33030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        fstart = start.replace(tzinfo=FEastern)
33040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        for wall in 0, 1, 1, 2, 3, 4:
33050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            expected = start.replace(hour=wall)
33060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = Eastern.fromutc(start)
33070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
33080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            expected = fstart + FEastern.stdoffset
33100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = FEastern.fromutc(fstart)
33110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
33120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            # Ensure astimezone() calls fromutc() too.
33140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            got = fstart.replace(tzinfo=utc_real).astimezone(FEastern)
33150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            self.assertEqual(expected, got)
33160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            start += HOUR
33180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi            fstart += HOUR
33190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#############################################################################
33220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# oddballs
33230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass Oddballs(unittest.TestCase):
33250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    def test_bug_1028306(self):
33270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Trying to compare a date to a datetime should act like a mixed-
33280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # type comparison, despite that datetime is a subclass of date.
33290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        as_date = date.today()
33300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        as_datetime = datetime.combine(as_date, time())
33310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(as_date != as_datetime)
33320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(as_datetime != as_date)
33330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not as_date == as_datetime)
33340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not as_datetime == as_date)
33350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: as_date < as_datetime)
33360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: as_datetime < as_date)
33370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: as_date <= as_datetime)
33380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: as_datetime <= as_date)
33390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: as_date > as_datetime)
33400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: as_datetime > as_date)
33410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: as_date >= as_datetime)
33420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertRaises(TypeError, lambda: as_datetime >= as_date)
33430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Neverthelss, comparison should work with the base-class (date)
33450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # projection if use of a date method is forced.
33460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(as_date.__eq__(as_datetime))
33470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        different_day = (as_date.day + 1) % 20 + 1
33480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertTrue(not as_date.__eq__(as_datetime.replace(day=
33490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                                     different_day)))
33500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # And date should compare with other subclasses of date.  If a
33520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # subclass wants to stop this, it's up to the subclass to do so.
33530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        date_sc = SubclassDate(as_date.year, as_date.month, as_date.day)
33540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(as_date, date_sc)
33550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(date_sc, as_date)
33560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        # Ditto for datetimes.
33580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        datetime_sc = SubclassDatetime(as_datetime.year, as_datetime.month,
33590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi                                       as_date.day, 0, 0, 0)
33600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(as_datetime, datetime_sc)
33610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi        self.assertEqual(datetime_sc, as_datetime)
33620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef test_main():
33640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    test_support.run_unittest(__name__)
33650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi
33660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiif __name__ == "__main__":
33670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi    test_main()
3368