14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""Test date/time type.
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSee http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom __future__ import division
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport pickle
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport cPickle
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport unittest
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom test import test_support
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom datetime import MINYEAR, MAXYEAR
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom datetime import timedelta
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom datetime import tzinfo
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom datetime import time
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom datetime import date, datetime
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpickle_choices = [(pickler, unpickler, proto)
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  for pickler in pickle, cPickle
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  for unpickler in pickle, cPickle
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  for proto in range(3)]
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmassert len(pickle_choices) == 2*2*3
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# An arbitrary collection of objects of non-datetime types, for testing
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# mixed-type comparisons.
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmOTHERSTUFF = (10, 10L, 34.5, "abc", {}, [], ())
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#############################################################################
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# module tests
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestModule(unittest.TestCase):
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_constants(self):
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import datetime
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(datetime.MINYEAR, 1)
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(datetime.MAXYEAR, 9999)
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#############################################################################
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# tzinfo tests
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass FixedOffset(tzinfo):
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __init__(self, offset, name, dstoffset=42):
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isinstance(offset, int):
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            offset = timedelta(minutes=offset)
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isinstance(dstoffset, int):
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dstoffset = timedelta(minutes=dstoffset)
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.__offset = offset
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.__name = name
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.__dstoffset = dstoffset
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __repr__(self):
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.__name.lower()
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def utcoffset(self, dt):
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.__offset
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tzname(self, dt):
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.__name
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def dst(self, dt):
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.__dstoffset
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PicklableFixedOffset(FixedOffset):
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __init__(self, offset=None, name=None, dstoffset=None):
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        FixedOffset.__init__(self, offset, name, dstoffset)
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestTZInfo(unittest.TestCase):
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_non_abstractness(self):
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # In order to allow subclasses to get pickled, the C implementation
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # wasn't able to get away with having __init__ raise
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # NotImplementedError.
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        useless = tzinfo()
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = datetime.max
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(NotImplementedError, useless.tzname, dt)
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(NotImplementedError, useless.utcoffset, dt)
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(NotImplementedError, useless.dst, dt)
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_subclass_must_override(self):
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class NotEnough(tzinfo):
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __init__(self, offset, name):
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.__offset = offset
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.__name = name
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(issubclass(NotEnough, tzinfo))
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ne = NotEnough(3, "NotByALongShot")
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(ne, tzinfo)
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = datetime.now()
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(NotImplementedError, ne.tzname, dt)
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(NotImplementedError, ne.utcoffset, dt)
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(NotImplementedError, ne.dst, dt)
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_normal(self):
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        fo = FixedOffset(3, "Three")
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(fo, tzinfo)
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for dt in datetime.now(), None:
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(fo.utcoffset(dt), timedelta(minutes=3))
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(fo.tzname(dt), "Three")
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(fo.dst(dt), timedelta(minutes=42))
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling_base(self):
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # There's no point to pickling tzinfo objects on their own (they
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # carry no data), but they need to be picklable anyway else
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # concrete subclasses can't be pickled.
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = tzinfo.__new__(tzinfo)
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(type(orig) is tzinfo)
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(type(derived) is tzinfo)
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling_subclass(self):
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Make sure we can pickle/unpickle an instance of a subclass.
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        offset = timedelta(minutes=-300)
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = PicklableFixedOffset(offset, 'cookie')
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(orig, tzinfo)
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(type(orig) is PicklableFixedOffset)
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(orig.utcoffset(None), offset)
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(orig.tzname(None), 'cookie')
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertIsInstance(derived, tzinfo)
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(type(derived) is PicklableFixedOffset)
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(derived.utcoffset(None), offset)
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(derived.tzname(None), 'cookie')
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#############################################################################
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Base clase for testing a particular aspect of timedelta, time, date and
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# datetime comparisons.
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass HarmlessMixedComparison:
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Test that __eq__ and __ne__ don't complain for mixed-type comparisons.
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Subclasses must define 'theclass', and theclass(1, 1, 1) must be a
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # legit constructor.
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_harmless_mixed_comparison(self):
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        me = self.theclass(1, 1, 1)
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertFalse(me == ())
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(me != ())
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertFalse(() == me)
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(() != me)
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIn(me, [1, 20L, [], me])
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIn([], [me, 1, 20L, []])
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_harmful_mixed_comparison(self):
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        me = self.theclass(1, 1, 1)
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: me < ())
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: me <= ())
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: me > ())
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: me >= ())
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: () < me)
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: () <= me)
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: () > me)
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: () >= me)
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, cmp, (), me)
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, cmp, me, ())
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#############################################################################
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# timedelta tests
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestTimeDelta(HarmlessMixedComparison, unittest.TestCase):
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    theclass = timedelta
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_constructor(self):
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq = self.assertEqual
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td = timedelta
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Check keyword args to constructor
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(), td(weeks=0, days=0, hours=0, minutes=0, seconds=0,
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    milliseconds=0, microseconds=0))
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(1), td(days=1))
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(0, 1), td(seconds=1))
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(0, 0, 1), td(microseconds=1))
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(weeks=1), td(days=7))
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(days=1), td(hours=24))
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(hours=1), td(minutes=60))
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(minutes=1), td(seconds=60))
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(seconds=1), td(milliseconds=1000))
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(milliseconds=1), td(microseconds=1000))
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Check float args to constructor
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(weeks=1.0/7), td(days=1))
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(days=1.0/24), td(hours=1))
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(hours=1.0/60), td(minutes=1))
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(minutes=1.0/60), td(seconds=1))
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(seconds=0.001), td(milliseconds=1))
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(milliseconds=0.001), td(microseconds=1))
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_computations(self):
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq = self.assertEqual
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td = timedelta
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = td(7) # One week
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = td(0, 60) # One minute
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        c = td(0, 0, 1000) # One millisecond
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(a+b+c, td(7, 60, 1000))
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(a-b, td(6, 24*3600 - 60))
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(-a, td(-7))
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(+a, td(7))
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(-b, td(-1, 24*3600 - 60))
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(-c, td(-1, 24*3600 - 1, 999000))
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(abs(a), a)
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(abs(-a), a)
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(6, 24*3600), a)
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(0, 0, 60*1000000), b)
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(a*10, td(70))
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(a*10, 10*a)
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(a*10L, 10*a)
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(b*10, td(0, 600))
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(10*b, td(0, 600))
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(b*10L, td(0, 600))
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(c*10, td(0, 0, 10000))
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(10*c, td(0, 0, 10000))
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(c*10L, td(0, 0, 10000))
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(a*-1, -a)
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(b*-2, -b-b)
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(c*-2, -c+-c)
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(b*(60*24), (b*60)*24)
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(b*(60*24), (60*b)*24)
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(c*1000, td(0, 1))
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(1000*c, td(0, 1))
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(a//7, td(1))
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(b//10, td(0, 6))
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(c//1000, td(0, 0, 1))
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(a//10, td(0, 7*24*360))
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(a//3600000, td(0, 0, 7*24*1000))
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Issue #11576
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(999999999, 86399, 999999) - td(999999999, 86399, 999998),
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           td(0, 0, 1))
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(999999999, 1, 1) - td(999999999, 1, 0),
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           td(0, 0, 1))
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_disallowed_computations(self):
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = timedelta(42)
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Add/sub ints, longs, floats should be illegal
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in 1, 1L, 1.0:
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: a+i)
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: a-i)
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: i+a)
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: i-a)
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Mul/div by float isn't supported.
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        x = 2.3
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a*x)
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: x*a)
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a/x)
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: x/a)
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a // x)
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: x // a)
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Division of int by timedelta doesn't make sense.
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Division by zero doesn't make sense.
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for zero in 0, 0L:
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: zero // a)
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ZeroDivisionError, lambda: a // zero)
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_basic_attributes(self):
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        days, seconds, us = 1, 7, 31
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td = timedelta(days, seconds, us)
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(td.days, days)
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(td.seconds, seconds)
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(td.microseconds, us)
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_total_seconds(self):
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td = timedelta(days=365)
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(td.total_seconds(), 31536000.0)
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for total_seconds in [123456.789012, -123456.789012, 0.123456, 0, 1e6]:
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            td = timedelta(seconds=total_seconds)
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(td.total_seconds(), total_seconds)
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Issue8644: Test that td.total_seconds() has the same
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # accuracy as td / timedelta(seconds=1).
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for ms in [-1, -2, -123]:
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            td = timedelta(microseconds=ms)
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(td.total_seconds(),
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ((24*3600*td.days + td.seconds)*10**6
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              + td.microseconds)/10**6)
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_carries(self):
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = timedelta(days=100,
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       weeks=-7,
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       hours=-24*(100-49),
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       minutes=-3,
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       seconds=12,
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       microseconds=(3*60 - 12) * 1e6 + 1)
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = timedelta(microseconds=1)
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_hash_equality(self):
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = timedelta(days=100,
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       weeks=-7,
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       hours=-24*(100-49),
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       minutes=-3,
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       seconds=12,
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       microseconds=(3*60 - 12) * 1000000)
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = timedelta()
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(t1), hash(t2))
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 += timedelta(weeks=7)
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 += timedelta(days=7*7)
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(t1), hash(t2))
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = {t1: 1}
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d[t2] = 2
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(d), 1)
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d[t1], 2)
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling(self):
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 12, 34, 56
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = timedelta(*args)
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_compare(self):
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = timedelta(2, 3, 4)
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = timedelta(2, 3, 4)
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 == t2)
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 <= t2)
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 >= t2)
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 != t2)
3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 < t2)
3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 > t2)
3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmp(t1, t2), 0)
3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmp(t2, t1), 0)
3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for args in (3, 3, 3), (2, 4, 4), (2, 3, 5):
3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t2 = timedelta(*args)   # this is larger than t1
3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 < t2)
3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 > t1)
3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 <= t2)
3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 >= t1)
3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 != t2)
3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 != t1)
3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 == t2)
3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 == t1)
3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 > t2)
3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 < t1)
3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 >= t2)
3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 <= t1)
3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(cmp(t1, t2), -1)
3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(cmp(t2, t1), 1)
3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for badarg in OTHERSTUFF:
3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t1 == badarg, False)
3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t1 != badarg, True)
3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(badarg == t1, False)
3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(badarg != t1, True)
3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 <= badarg)
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 < badarg)
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 > badarg)
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 >= badarg)
3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg <= t1)
3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg < t1)
3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg > t1)
3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg >= t1)
3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_str(self):
3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td = timedelta
3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq = self.assertEqual
3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(str(td(1)), "1 day, 0:00:00")
3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(str(td(-1)), "-1 day, 0:00:00")
3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(str(td(2)), "2 days, 0:00:00")
3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(str(td(-2)), "-2 days, 0:00:00")
3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(str(td(hours=12, minutes=58, seconds=59)), "12:58:59")
3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(str(td(hours=2, minutes=3, seconds=4)), "2:03:04")
3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(str(td(weeks=-30, hours=23, minutes=12, seconds=34)),
3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           "-210 days, 23:12:34")
3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(str(td(milliseconds=1)), "0:00:00.001000")
3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(str(td(microseconds=3)), "0:00:00.000003")
3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(str(td(days=999999999, hours=23, minutes=59, seconds=59,
3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   microseconds=999999)),
3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           "999999999 days, 23:59:59.999999")
3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_roundtrip(self):
3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for td in (timedelta(days=999999999, hours=23, minutes=59,
3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             seconds=59, microseconds=999999),
3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   timedelta(days=-999999999),
3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   timedelta(days=1, seconds=2, microseconds=3)):
3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Verify td -> string -> td identity.
3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s = repr(td)
3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(s.startswith('datetime.'))
3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s = s[9:]
4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            td2 = eval(s)
4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(td, td2)
4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Verify identity via reconstructing from pieces.
4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            td2 = timedelta(td.days, td.seconds, td.microseconds)
4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(td, td2)
4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_resolution_info(self):
4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(timedelta.min, timedelta)
4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(timedelta.max, timedelta)
4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(timedelta.resolution, timedelta)
4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(timedelta.max > timedelta.min)
4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(timedelta.min, timedelta(-999999999))
4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(timedelta.max, timedelta(999999999, 24*3600-1, 1e6-1))
4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(timedelta.resolution, timedelta(0, 0, 1))
4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_overflow(self):
4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tiny = timedelta.resolution
4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td = timedelta.min + tiny
4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td -= tiny  # no problem
4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(OverflowError, td.__sub__, tiny)
4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(OverflowError, td.__add__, -tiny)
4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td = timedelta.max - tiny
4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td += tiny  # no problem
4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(OverflowError, td.__add__, tiny)
4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(OverflowError, td.__sub__, -tiny)
4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(OverflowError, lambda: -timedelta.max)
4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_microsecond_rounding(self):
4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td = timedelta
4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq = self.assertEqual
4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Single-field rounding.
4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(milliseconds=0.4/1000), td(0))    # rounds to 0
4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(milliseconds=-0.4/1000), td(0))    # rounds to 0
4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(milliseconds=0.6/1000), td(microseconds=1))
4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(milliseconds=-0.6/1000), td(microseconds=-1))
4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Rounding due to contributions from more than one field.
4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        us_per_hour = 3600e6
4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        us_per_day = us_per_hour * 24
4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(days=.4/us_per_day), td(0))
4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(hours=.2/us_per_hour), td(0))
4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(days=.4/us_per_day, hours=.2/us_per_hour), td(microseconds=1))
4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(days=-.4/us_per_day), td(0))
4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(hours=-.2/us_per_hour), td(0))
4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        eq(td(days=-.4/us_per_day, hours=-.2/us_per_hour), td(microseconds=-1))
4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_massive_normalization(self):
4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        td = timedelta(microseconds=-1)
4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((td.days, td.seconds, td.microseconds),
4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         (-1, 24*3600-1, 999999))
4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bool(self):
4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(timedelta(1))
4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(timedelta(0, 1))
4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(timedelta(0, 0, 1))
4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(timedelta(microseconds=1))
4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not timedelta(0))
4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_subclass_timedelta(self):
4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class T(timedelta):
4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            @staticmethod
4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def from_td(td):
4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return T(td.days, td.seconds, td.microseconds)
4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def as_hours(self):
4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                sum = (self.days * 24 +
4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       self.seconds / 3600.0 +
4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       self.microseconds / 3600e6)
4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return round(sum)
4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = T(days=1)
4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(type(t1) is T)
4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.as_hours(), 24)
4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = T(days=-1, seconds=-3600)
4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(type(t2) is T)
4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.as_hours(), -25)
4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t3 = t1 + t2
4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(type(t3) is timedelta)
4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t4 = T.from_td(t3)
4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(type(t4) is T)
4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.days, t4.days)
4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.seconds, t4.seconds)
4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.microseconds, t4.microseconds)
4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t3), str(t4))
4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t4.as_hours(), -1)
4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#############################################################################
4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# date tests
4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestDateOnly(unittest.TestCase):
4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Tests here won't pass if also run on datetime objects, so don't
5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # subclass this to test datetimes too.
5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_delta_non_days_ignored(self):
5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = date(2000, 1, 2)
5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        delta = timedelta(days=1, hours=2, minutes=3, seconds=4,
5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          microseconds=5)
5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        days = timedelta(delta.days)
5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(days, timedelta(1))
5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = dt + delta
5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2, dt + days)
5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = delta + dt
5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2, dt + days)
5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = dt - delta
5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2, dt - days)
5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        delta = -delta
5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        days = timedelta(delta.days)
5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(days, timedelta(-2))
5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = dt + delta
5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2, dt + days)
5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = delta + dt
5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2, dt + days)
5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = dt - delta
5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2, dt - days)
5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass SubclassDate(date):
5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sub_var = 1
5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestDate(HarmlessMixedComparison, unittest.TestCase):
5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Tests here should pass for both dates and datetimes, except for a
5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # few tests that TestDateTime overrides.
5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    theclass = date
5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_basic_attributes(self):
5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = self.theclass(2002, 3, 1)
5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.year, 2002)
5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.month, 3)
5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.day, 1)
5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_roundtrip(self):
5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for dt in (self.theclass(1, 2, 3),
5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   self.theclass.today()):
5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Verify dt -> string -> date identity.
5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s = repr(dt)
5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(s.startswith('datetime.'))
5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s = s[9:]
5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dt2 = eval(s)
5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(dt, dt2)
5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Verify identity via reconstructing from pieces.
5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dt2 = self.theclass(dt.year, dt.month, dt.day)
5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(dt, dt2)
5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_ordinal_conversions(self):
5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Check some fixed values.
5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for y, m, d, n in [(1, 1, 1, 1),      # calendar origin
5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           (1, 12, 31, 365),
5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           (2, 1, 1, 366),
5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           # first example from "Calendrical Calculations"
5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           (1945, 11, 12, 710347)]:
5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(y, m, d)
5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(n, d.toordinal())
5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            fromord = self.theclass.fromordinal(n)
5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d, fromord)
5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if hasattr(fromord, "hour"):
5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # if we're checking something fancier than a date, verify
5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # the extra fields have been zeroed out
5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(fromord.hour, 0)
5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(fromord.minute, 0)
5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(fromord.second, 0)
5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(fromord.microsecond, 0)
5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Check first and last days of year spottily across the whole
5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # range of years supported.
5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for year in xrange(MINYEAR, MAXYEAR+1, 7):
5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Verify (year, 1, 1) -> ordinal -> y, m, d is identity.
5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(year, 1, 1)
5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            n = d.toordinal()
5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d2 = self.theclass.fromordinal(n)
5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d, d2)
5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Verify that moving back a day gets to the end of year-1.
5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if year > 1:
5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                d = self.theclass.fromordinal(n-1)
5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                d2 = self.theclass(year-1, 12, 31)
5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(d, d2)
5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(d2.toordinal(), n-1)
5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test every day in a leap-year and a non-leap year.
5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dim = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for year, isleap in (2000, True), (2002, False):
5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            n = self.theclass(year, 1, 1).toordinal()
5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for month, maxday in zip(range(1, 13), dim):
5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if month == 2 and isleap:
6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    maxday += 1
6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                for day in range(1, maxday+1):
6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    d = self.theclass(year, month, day)
6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self.assertEqual(d.toordinal(), n)
6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self.assertEqual(d, self.theclass.fromordinal(n))
6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    n += 1
6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_extreme_ordinals(self):
6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = self.theclass.min
6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = self.theclass(a.year, a.month, a.day)  # get rid of time parts
6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        aord = a.toordinal()
6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = a.fromordinal(aord)
6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a, b)
6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, lambda: a.fromordinal(aord - 1))
6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = a + timedelta(days=1)
6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(b.toordinal(), aord + 1)
6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(b, self.theclass.fromordinal(aord + 1))
6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = self.theclass.max
6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = self.theclass(a.year, a.month, a.day)  # get rid of time parts
6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        aord = a.toordinal()
6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = a.fromordinal(aord)
6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a, b)
6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, lambda: a.fromordinal(aord + 1))
6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = a - timedelta(days=1)
6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(b.toordinal(), aord - 1)
6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(b, self.theclass.fromordinal(aord - 1))
6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bad_constructor_arguments(self):
6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad years
6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(MINYEAR, 1, 1)  # no exception
6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(MAXYEAR, 1, 1)  # no exception
6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1)
6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1)
6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad months
6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 1, 1)    # no exception
6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 12, 1)   # no exception
6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 0, 1)
6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 13, 1)
6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad days
6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 2, 29)   # no exception
6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2004, 2, 29)   # no exception
6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2400, 2, 29)   # no exception
6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 2, 30)
6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2001, 2, 29)
6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2100, 2, 29)
6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 1900, 2, 29)
6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 1, 0)
6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 1, 32)
6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_hash_equality(self):
6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = self.theclass(2000, 12, 31)
6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # same thing
6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        e = self.theclass(2000, 12, 31)
6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d, e)
6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(d), hash(e))
6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic = {d: 1}
6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic[e] = 2
6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(dic), 1)
6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[d], 2)
6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[e], 2)
6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = self.theclass(2001,  1,  1)
6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # same thing
6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        e = self.theclass(2001,  1,  1)
6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d, e)
6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(d), hash(e))
6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic = {d: 1}
6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic[e] = 2
6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(dic), 1)
6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[d], 2)
6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[e], 2)
6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_computations(self):
6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = self.theclass(2002, 1, 31)
6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = self.theclass(1956, 1, 31)
6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        diff = a-b
6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4)))
6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(diff.seconds, 0)
6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(diff.microseconds, 0)
6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        day = timedelta(1)
6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        week = timedelta(7)
6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = self.theclass(2002, 3, 2)
6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a + day, self.theclass(2002, 3, 3))
6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(day + a, self.theclass(2002, 3, 3))
6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - day, self.theclass(2002, 3, 1))
6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(-day + a, self.theclass(2002, 3, 1))
6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a + week, self.theclass(2002, 3, 9))
6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - week, self.theclass(2002, 2, 23))
6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a + 52*week, self.theclass(2003, 3, 1))
6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - 52*week, self.theclass(2001, 3, 3))
6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a + week) - a, week)
7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a + day) - a, day)
7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a - week) - a, -week)
7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a - day) - a, -day)
7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a + week), -week)
7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a + day), -day)
7054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a - week), week)
7064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a - day), day)
7074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Add/sub ints, longs, floats should be illegal
7094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in 1, 1L, 1.0:
7104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: a+i)
7114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: a-i)
7124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: i+a)
7134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: i-a)
7144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # delta - date is senseless.
7164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: day - a)
7174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # mixing date and (delta or date) via * or // is senseless
7184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: day * a)
7194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a * day)
7204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: day // a)
7214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a // day)
7224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a * a)
7234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a // a)
7244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # date + date is senseless
7254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a + a)
7264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_overflow(self):
7284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tiny = self.theclass.resolution
7294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for delta in [tiny, timedelta(1), timedelta(2)]:
7314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dt = self.theclass.min + delta
7324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dt -= delta  # no problem
7334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(OverflowError, dt.__sub__, delta)
7344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(OverflowError, dt.__add__, -delta)
7354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dt = self.theclass.max - delta
7374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dt += delta  # no problem
7384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(OverflowError, dt.__add__, delta)
7394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(OverflowError, dt.__sub__, -delta)
7404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_fromtimestamp(self):
7424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import time
7434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try an arbitrary fixed value.
7454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        year, month, day = 1999, 9, 19
7464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ts = time.mktime((year, month, day, 0, 0, 0, 0, 0, -1))
7474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = self.theclass.fromtimestamp(ts)
7484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d.year, year)
7494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d.month, month)
7504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d.day, day)
7514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_insane_fromtimestamp(self):
7534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # It's possible that some platform maps time_t to double,
7544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # and that this test will fail there.  This test should
7554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # exempt such platforms (provided they return reasonable
7564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # results!).
7574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for insane in -1e200, 1e200:
7584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ValueError, self.theclass.fromtimestamp,
7594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              insane)
7604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_today(self):
7624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import time
7634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # We claim that today() is like fromtimestamp(time.time()), so
7654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # prove it.
7664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for dummy in range(3):
7674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            today = self.theclass.today()
7684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ts = time.time()
7694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            todayagain = self.theclass.fromtimestamp(ts)
7704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if today == todayagain:
7714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                break
7724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # There are several legit reasons that could fail:
7734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # 1. It recently became midnight, between the today() and the
7744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #    time() calls.
7754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # 2. The platform time() has such fine resolution that we'll
7764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #    never get the same value twice.
7774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # 3. The platform time() has poor resolution, and we just
7784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #    happened to call today() right before a resolution quantum
7794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #    boundary.
7804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # 4. The system clock got fiddled between calls.
7814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # In any case, wait a little while and try again.
7824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            time.sleep(0.1)
7834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # It worked or it didn't.  If it didn't, assume it's reason #2, and
7854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # let the test pass if they're within half a second of each other.
7864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(today == todayagain or
7874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        abs(todayagain - today) < timedelta(seconds=0.5))
7884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_weekday(self):
7904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in range(7):
7914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # March 4, 2002 is a Monday
7924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(self.theclass(2002, 3, 4+i).weekday(), i)
7934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(self.theclass(2002, 3, 4+i).isoweekday(), i+1)
7944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # January 2, 1956 is a Monday
7954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(self.theclass(1956, 1, 2+i).weekday(), i)
7964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(self.theclass(1956, 1, 2+i).isoweekday(), i+1)
7974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_isocalendar(self):
7994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Check examples from
8004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
8014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in range(7):
8024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(2003, 12, 22+i)
8034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.isocalendar(), (2003, 52, i+1))
8044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(2003, 12, 29) + timedelta(i)
8054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.isocalendar(), (2004, 1, i+1))
8064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(2004, 1, 5+i)
8074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.isocalendar(), (2004, 2, i+1))
8084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(2009, 12, 21+i)
8094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.isocalendar(), (2009, 52, i+1))
8104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(2009, 12, 28) + timedelta(i)
8114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.isocalendar(), (2009, 53, i+1))
8124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(2010, 1, 4+i)
8134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.isocalendar(), (2010, 1, i+1))
8144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_iso_long_years(self):
8164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Calculate long ISO years and compare to table from
8174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
8184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ISO_LONG_YEARS_TABLE = """
8194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm              4   32   60   88
8204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm              9   37   65   93
8214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm             15   43   71   99
8224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm             20   48   76
8234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm             26   54   82
8244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            105  133  161  189
8264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            111  139  167  195
8274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            116  144  172
8284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            122  150  178
8294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            128  156  184
8304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            201  229  257  285
8324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            207  235  263  291
8334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            212  240  268  296
8344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            218  246  274
8354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            224  252  280
8364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            303  331  359  387
8384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            308  336  364  392
8394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            314  342  370  398
8404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            320  348  376
8414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            325  353  381
8424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """
8434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        iso_long_years = map(int, ISO_LONG_YEARS_TABLE.split())
8444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        iso_long_years.sort()
8454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        L = []
8464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in range(400):
8474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(2000+i, 12, 31)
8484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d1 = self.theclass(1600+i, 12, 31)
8494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.isocalendar()[1:], d1.isocalendar()[1:])
8504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if d.isocalendar()[1] == 53:
8514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                L.append(i)
8524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(L, iso_long_years)
8534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_isoformat(self):
8554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(2, 3, 2)
8564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), "0002-03-02")
8574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_ctime(self):
8594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(2002, 3, 2)
8604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.ctime(), "Sat Mar  2 00:00:00 2002")
8614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_strftime(self):
8634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(2005, 3, 2)
8644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.strftime("m:%m d:%d y:%y"), "m:03 d:02 y:05")
8654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.strftime(""), "") # SF bug #761337
8664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.strftime('x'*1000), 'x'*1000) # SF bug #1556784
8674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t.strftime) # needs an arg
8694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t.strftime, "one", "two") # too many args
8704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t.strftime, 42) # arg wrong type
8714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # test that unicode input is allowed (issue 2782)
8734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.strftime(u"%m"), "03")
8744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A naive object replaces %z and %Z w/ empty strings.
8764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
8774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #make sure that invalid format specifiers are handled correctly
8794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #self.assertRaises(ValueError, t.strftime, "%e")
8804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #self.assertRaises(ValueError, t.strftime, "%")
8814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #self.assertRaises(ValueError, t.strftime, "%#")
8824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #oh well, some systems just ignore those invalid ones.
8844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #at least, excercise them to make sure that no crashes
8854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #are generated
8864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for f in ["%e", "%", "%#"]:
8874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
8884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                t.strftime(f)
8894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except ValueError:
8904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
8914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #check that this standard extension works
8934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t.strftime("%f")
8944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_format(self):
8974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = self.theclass(2007, 9, 10)
8984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.__format__(''), str(dt))
8994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # check that a derived class's __str__() gets called
9014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class A(self.theclass):
9024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __str__(self):
9034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return 'A'
9044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = A(2007, 9, 10)
9054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.__format__(''), 'A')
9064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # check that a derived class's strftime gets called
9084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class B(self.theclass):
9094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def strftime(self, format_spec):
9104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return 'B'
9114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = B(2007, 9, 10)
9124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(b.__format__(''), str(dt))
9134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for fmt in ["m:%m d:%d y:%y",
9154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    "m:%m d:%d y:%y H:%H M:%M S:%S",
9164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    "%z %Z",
9174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    ]:
9184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(dt.__format__(fmt), dt.strftime(fmt))
9194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(a.__format__(fmt), dt.strftime(fmt))
9204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(b.__format__(fmt), 'B')
9214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_resolution_info(self):
9234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(self.theclass.min, self.theclass)
9244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(self.theclass.max, self.theclass)
9254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(self.theclass.resolution, timedelta)
9264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(self.theclass.max > self.theclass.min)
9274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_extreme_timedelta(self):
9294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        big = self.theclass.max - self.theclass.min
9304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds
9314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds
9324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # n == 315537897599999999 ~= 2**58.13
9334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        justasbig = timedelta(0, 0, n)
9344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(big, justasbig)
9354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(self.theclass.min + big, self.theclass.max)
9364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(self.theclass.max - big, self.theclass.min)
9374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_timetuple(self):
9394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in range(7):
9404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # January 2, 1956 is a Monday (0)
9414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(1956, 1, 2+i)
9424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t = d.timetuple()
9434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t, (1956, 1, 2+i, 0, 0, 0, i, 2+i, -1))
9444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # February 1, 1956 is a Wednesday (2)
9454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(1956, 2, 1+i)
9464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t = d.timetuple()
9474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t, (1956, 2, 1+i, 0, 0, 0, (2+i)%7, 32+i, -1))
9484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # March 1, 1956 is a Thursday (3), and is the 31+29+1 = 61st day
9494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # of the year.
9504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = self.theclass(1956, 3, 1+i)
9514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t = d.timetuple()
9524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t, (1956, 3, 1+i, 0, 0, 0, (3+i)%7, 61+i, -1))
9534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t.tm_year, 1956)
9544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t.tm_mon, 3)
9554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t.tm_mday, 1+i)
9564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t.tm_hour, 0)
9574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t.tm_min, 0)
9584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t.tm_sec, 0)
9594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t.tm_wday, (3+i)%7)
9604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t.tm_yday, 61+i)
9614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t.tm_isdst, -1)
9624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling(self):
9644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 6, 7, 23
9654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = self.theclass(*args)
9664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
9674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
9684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
9694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
9704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_compare(self):
9724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(2, 3, 4)
9734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass(2, 3, 4)
9744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 == t2)
9754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 <= t2)
9764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 >= t2)
9774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 != t2)
9784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 < t2)
9794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 > t2)
9804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmp(t1, t2), 0)
9814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmp(t2, t1), 0)
9824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for args in (3, 3, 3), (2, 4, 4), (2, 3, 5):
9844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t2 = self.theclass(*args)   # this is larger than t1
9854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 < t2)
9864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 > t1)
9874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 <= t2)
9884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 >= t1)
9894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 != t2)
9904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 != t1)
9914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 == t2)
9924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 == t1)
9934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 > t2)
9944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 < t1)
9954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 >= t2)
9964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 <= t1)
9974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(cmp(t1, t2), -1)
9984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(cmp(t2, t1), 1)
9994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for badarg in OTHERSTUFF:
10014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t1 == badarg, False)
10024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t1 != badarg, True)
10034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(badarg == t1, False)
10044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(badarg != t1, True)
10054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 < badarg)
10074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 > badarg)
10084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 >= badarg)
10094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg <= t1)
10104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg < t1)
10114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg > t1)
10124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg >= t1)
10134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_mixed_compare(self):
10154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        our = self.theclass(2000, 4, 5)
10164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, cmp, our, 1)
10174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, cmp, 1, our)
10184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class AnotherDateTimeClass(object):
10204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __cmp__(self, other):
10214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Return "equal" so calling this can't be confused with
10224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # compare-by-address (which never says "equal" for distinct
10234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # objects).
10244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return 0
10254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            __hash__ = None # Silence Py3k warning
10264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # This still errors, because date and datetime comparison raise
10284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # TypeError instead of NotImplemented when they don't know what to
10294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # do, in order to stop comparison from falling back to the default
10304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # compare-by-address.
10314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        their = AnotherDateTimeClass()
10324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, cmp, our, their)
10334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Oops:  The next stab raises TypeError in the C implementation,
10344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # but not in the Python implementation of datetime.  The difference
10354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # is due to that the Python implementation defines __cmp__ but
10364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # the C implementation defines tp_richcompare.  This is more pain
10374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # to fix than it's worth, so commenting out the test.
10384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # self.assertEqual(cmp(their, our), 0)
10394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # But date and datetime comparison return NotImplemented instead if the
10414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # other object has a timetuple attr.  This gives the other object a
10424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # chance to do the comparison.
10434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class Comparable(AnotherDateTimeClass):
10444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def timetuple(self):
10454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return ()
10464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        their = Comparable()
10484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmp(our, their), 0)
10494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmp(their, our), 0)
10504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(our == their)
10514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(their == our)
10524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bool(self):
10544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # All dates are considered true.
10554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(self.theclass.min)
10564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(self.theclass.max)
10574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_strftime_out_of_range(self):
10594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # For nasty technical reasons, we can't handle years before 1900.
10604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
10614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cls(1900, 1, 1).strftime("%Y"), "1900")
10624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for y in 1, 49, 51, 99, 100, 1000, 1899:
10634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ValueError, cls(y, 1, 1).strftime, "%Y")
10644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_replace(self):
10664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
10674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = [1, 2, 3]
10684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(*args)
10694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(base, base.replace())
10704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        i = 0
10724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for name, newval in (("year", 2),
10734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("month", 3),
10744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("day", 4)):
10754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs = args[:]
10764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs[i] = newval
10774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            expected = cls(*newargs)
10784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = base.replace(**{name: newval})
10794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
10804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            i += 1
10814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Out of bounds.
10834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(2000, 2, 29)
10844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, year=2001)
10854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_subclass_date(self):
10874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class C(self.theclass):
10894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            theAnswer = 42
10904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __new__(cls, *args, **kws):
10924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                temp = kws.copy()
10934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                extra = temp.pop('extra')
10944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                result = self.theclass.__new__(cls, *args, **temp)
10954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                result.extra = extra
10964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return result
10974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def newmeth(self, start):
10994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return start + self.year + self.month
11004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 2003, 4, 14
11024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt1 = self.theclass(*args)
11044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = C(*args, **{'extra': 7})
11054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.__class__, C)
11074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.theAnswer, 42)
11084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.extra, 7)
11094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt1.toordinal(), dt2.toordinal())
11104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month - 7)
11114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling_subclass_date(self):
11134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 6, 7, 23
11154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = SubclassDate(*args)
11164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
11174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
11184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
11194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
11204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_backdoor_resistance(self):
11224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # For fast unpickling, the constructor accepts a pickle string.
11234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # This is a low-overhead backdoor.  A user can (by intent or
11244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # mistake) pass a string directly, which (if it's the right length)
11254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # will get treated like a pickle, and bypass the normal sanity
11264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # checks in the constructor.  This can create insane objects.
11274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # The constructor doesn't want to burn the time to validate all
11284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # fields, but does check the month field.  This stops, e.g.,
11294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # datetime.datetime('1995-03-25') from yielding an insane object.
11304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = '1995-03-25'
11314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not issubclass(self.theclass, datetime):
11324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            base = base[:4]
11334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for month_byte in '9', chr(0), chr(13), '\xff':
11344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, self.theclass,
11354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                         base[:2] + month_byte + base[3:])
11364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for ord_byte in range(1, 13):
11374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # This shouldn't blow up because of the month byte alone.  If
11384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # the implementation changes to do more-careful checking, it may
11394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # blow up because other fields are insane.
11404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.theclass(base[:2] + chr(ord_byte) + base[3:])
11414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#############################################################################
11434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# datetime tests
11444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass SubclassDatetime(datetime):
11464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sub_var = 1
11474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestDateTime(TestDate):
11494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    theclass = datetime
11514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_basic_attributes(self):
11534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = self.theclass(2002, 3, 1, 12, 0)
11544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.year, 2002)
11554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.month, 3)
11564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.day, 1)
11574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.hour, 12)
11584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.minute, 0)
11594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.second, 0)
11604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.microsecond, 0)
11614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_basic_attributes_nonzero(self):
11634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Make sure all attributes are non-zero so bugs in
11644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bit-shifting access show up.
11654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = self.theclass(2002, 3, 1, 12, 59, 59, 8000)
11664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.year, 2002)
11674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.month, 3)
11684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.day, 1)
11694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.hour, 12)
11704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.minute, 59)
11714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.second, 59)
11724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.microsecond, 8000)
11734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_roundtrip(self):
11754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7),
11764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                   self.theclass.now()):
11774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Verify dt -> string -> datetime identity.
11784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s = repr(dt)
11794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(s.startswith('datetime.'))
11804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s = s[9:]
11814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dt2 = eval(s)
11824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(dt, dt2)
11834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Verify identity via reconstructing from pieces.
11854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dt2 = self.theclass(dt.year, dt.month, dt.day,
11864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                dt.hour, dt.minute, dt.second,
11874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                dt.microsecond)
11884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(dt, dt2)
11894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_isoformat(self):
11914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(2, 3, 2, 4, 5, 1, 123)
11924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(),    "0002-03-02T04:05:01.000123")
11934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat('T'), "0002-03-02T04:05:01.000123")
11944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123")
11954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat('\x00'), "0002-03-02\x0004:05:01.000123")
11964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # str is ISO format with the separator forced to a blank.
11974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t), "0002-03-02 04:05:01.000123")
11984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
11994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(2, 3, 2)
12004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(),    "0002-03-02T00:00:00")
12014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat('T'), "0002-03-02T00:00:00")
12024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(' '), "0002-03-02 00:00:00")
12034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # str is ISO format with the separator forced to a blank.
12044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t), "0002-03-02 00:00:00")
12054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_format(self):
12074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = self.theclass(2007, 9, 10, 4, 5, 1, 123)
12084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.__format__(''), str(dt))
12094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # check that a derived class's __str__() gets called
12114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class A(self.theclass):
12124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __str__(self):
12134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return 'A'
12144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = A(2007, 9, 10, 4, 5, 1, 123)
12154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.__format__(''), 'A')
12164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # check that a derived class's strftime gets called
12184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class B(self.theclass):
12194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def strftime(self, format_spec):
12204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return 'B'
12214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = B(2007, 9, 10, 4, 5, 1, 123)
12224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(b.__format__(''), str(dt))
12234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for fmt in ["m:%m d:%d y:%y",
12254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    "m:%m d:%d y:%y H:%H M:%M S:%S",
12264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    "%z %Z",
12274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    ]:
12284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(dt.__format__(fmt), dt.strftime(fmt))
12294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(a.__format__(fmt), dt.strftime(fmt))
12304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(b.__format__(fmt), 'B')
12314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_more_ctime(self):
12334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test fields that TestDate doesn't touch.
12344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import time
12354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(2002, 3, 2, 18, 3, 5, 123)
12374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.ctime(), "Sat Mar  2 18:03:05 2002")
12384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Oops!  The next line fails on Win2K under MSVC 6, so it's commented
12394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # out.  The difference is that t.ctime() produces " 2" for the day,
12404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # but platform ctime() produces "02" for the day.  According to
12414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # C99, t.ctime() is correct here.
12424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # self.assertEqual(t.ctime(), time.ctime(time.mktime(t.timetuple())))
12434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # So test a case where that difference doesn't matter.
12454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(2002, 3, 22, 18, 3, 5, 123)
12464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.ctime(), time.ctime(time.mktime(t.timetuple())))
12474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tz_independent_comparing(self):
12494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt1 = self.theclass(2002, 3, 1, 9, 0, 0)
12504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = self.theclass(2002, 3, 1, 10, 0, 0)
12514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt3 = self.theclass(2002, 3, 1, 9, 0, 0)
12524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt1, dt3)
12534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(dt2 > dt3)
12544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Make sure comparison doesn't forget microseconds, and isn't done
12564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # via comparing a float timestamp (an IEEE double doesn't have enough
12574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # precision to span microsecond resolution across years 1 thru 9999,
12584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # so comparing via timestamp necessarily calls some distinct values
12594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # equal).
12604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998)
12614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        us = timedelta(microseconds=1)
12624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = dt1 + us
12634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2 - dt1, us)
12644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(dt1 < dt2)
12654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_strftime_with_bad_tzname_replace(self):
12674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # verify ok if tzinfo.tzname().replace() returns a non-string
12684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class MyTzInfo(FixedOffset):
12694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def tzname(self, dt):
12704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                class MyStr(str):
12714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    def replace(self, *args):
12724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        return None
12734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return MyStr('name')
12744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(2005, 3, 2, 0, 0, 0, 0, MyTzInfo(3, 'name'))
12754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t.strftime, '%Z')
12764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
12774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bad_constructor_arguments(self):
12784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad years
12794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(MINYEAR, 1, 1)  # no exception
12804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(MAXYEAR, 1, 1)  # no exception
12814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1)
12824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1)
12834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad months
12844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 1, 1)    # no exception
12854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 12, 1)   # no exception
12864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 0, 1)
12874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 13, 1)
12884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad days
12894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 2, 29)   # no exception
12904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2004, 2, 29)   # no exception
12914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2400, 2, 29)   # no exception
12924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 2, 30)
12934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2001, 2, 29)
12944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2100, 2, 29)
12954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 1900, 2, 29)
12964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 1, 0)
12974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 1, 32)
12984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad hours
12994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 1, 31, 0)    # no exception
13004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 1, 31, 23)   # no exception
13014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, -1)
13024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 24)
13034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad minutes
13044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 1, 31, 23, 0)    # no exception
13054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 1, 31, 23, 59)   # no exception
13064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, -1)
13074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 60)
13084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad seconds
13094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 1, 31, 23, 59, 0)    # no exception
13104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 1, 31, 23, 59, 59)   # no exception
13114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, -1)
13124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, 60)
13134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad microseconds
13144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 1, 31, 23, 59, 59, 0)    # no exception
13154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(2000, 1, 31, 23, 59, 59, 999999)   # no exception
13164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass,
13174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          2000, 1, 31, 23, 59, 59, -1)
13184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass,
13194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          2000, 1, 31, 23, 59, 59,
13204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          1000000)
13214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_hash_equality(self):
13234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = self.theclass(2000, 12, 31, 23, 30, 17)
13244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        e = self.theclass(2000, 12, 31, 23, 30, 17)
13254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d, e)
13264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(d), hash(e))
13274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic = {d: 1}
13294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic[e] = 2
13304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(dic), 1)
13314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[d], 2)
13324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[e], 2)
13334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = self.theclass(2001,  1,  1,  0,  5, 17)
13354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        e = self.theclass(2001,  1,  1,  0,  5, 17)
13364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d, e)
13374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(d), hash(e))
13384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic = {d: 1}
13404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic[e] = 2
13414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(dic), 1)
13424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[d], 2)
13434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[e], 2)
13444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
13454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_computations(self):
13464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = self.theclass(2002, 1, 31)
13474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = self.theclass(1956, 1, 31)
13484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        diff = a-b
13494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4)))
13504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(diff.seconds, 0)
13514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(diff.microseconds, 0)
13524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = self.theclass(2002, 3, 2, 17, 6)
13534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        millisec = timedelta(0, 0, 1000)
13544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        hour = timedelta(0, 3600)
13554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        day = timedelta(1)
13564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        week = timedelta(7)
13574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a + hour, self.theclass(2002, 3, 2, 18, 6))
13584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hour + a, self.theclass(2002, 3, 2, 18, 6))
13594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a + 10*hour, self.theclass(2002, 3, 3, 3, 6))
13604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - hour, self.theclass(2002, 3, 2, 16, 6))
13614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(-hour + a, self.theclass(2002, 3, 2, 16, 6))
13624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - hour, a + -hour)
13634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - 20*hour, self.theclass(2002, 3, 1, 21, 6))
13644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a + day, self.theclass(2002, 3, 3, 17, 6))
13654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - day, self.theclass(2002, 3, 1, 17, 6))
13664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a + week, self.theclass(2002, 3, 9, 17, 6))
13674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - week, self.theclass(2002, 2, 23, 17, 6))
13684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a + 52*week, self.theclass(2003, 3, 1, 17, 6))
13694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - 52*week, self.theclass(2001, 3, 3, 17, 6))
13704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a + week) - a, week)
13714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a + day) - a, day)
13724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a + hour) - a, hour)
13734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a + millisec) - a, millisec)
13744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a - week) - a, -week)
13754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a - day) - a, -day)
13764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a - hour) - a, -hour)
13774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual((a - millisec) - a, -millisec)
13784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a + week), -week)
13794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a + day), -day)
13804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a + hour), -hour)
13814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a + millisec), -millisec)
13824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a - week), week)
13834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a - day), day)
13844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a - hour), hour)
13854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (a - millisec), millisec)
13864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a + (week + day + hour + millisec),
13874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         self.theclass(2002, 3, 10, 18, 6, 0, 1000))
13884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a + (week + day + hour + millisec),
13894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         (((a + week) + day) + hour) + millisec)
13904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (week + day + hour + millisec),
13914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         self.theclass(2002, 2, 22, 16, 5, 59, 999000))
13924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a - (week + day + hour + millisec),
13934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         (((a - week) - day) - hour) - millisec)
13944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Add/sub ints, longs, floats should be illegal
13954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in 1, 1L, 1.0:
13964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: a+i)
13974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: a-i)
13984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: i+a)
13994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: i-a)
14004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # delta - datetime is senseless.
14024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: day - a)
14034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # mixing datetime and (delta or datetime) via * or // is senseless
14044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: day * a)
14054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a * day)
14064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: day // a)
14074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a // day)
14084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a * a)
14094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a // a)
14104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # datetime + datetime is senseless
14114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: a + a)
14124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling(self):
14144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 6, 7, 23, 20, 59, 1, 64**2
14154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = self.theclass(*args)
14164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
14174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
14184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
14194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
14204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_more_pickling(self):
14224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = self.theclass(2003, 2, 7, 16, 48, 37, 444116)
14234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = pickle.dumps(a)
14244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = pickle.loads(s)
14254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(b.year, 2003)
14264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(b.month, 2)
14274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(b.day, 7)
14284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling_subclass_datetime(self):
14304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 6, 7, 23, 20, 59, 1, 64**2
14314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = SubclassDatetime(*args)
14324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
14334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
14344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
14354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
14364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_more_compare(self):
14384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # The test_compare() inherited from TestDate covers the error cases.
14394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # We just want to test lexicographic ordering on the members datetime
14404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # has that date lacks.
14414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = [2000, 11, 29, 20, 58, 16, 999998]
14424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(*args)
14434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass(*args)
14444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 == t2)
14454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 <= t2)
14464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 >= t2)
14474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 != t2)
14484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 < t2)
14494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 > t2)
14504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmp(t1, t2), 0)
14514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmp(t2, t1), 0)
14524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in range(len(args)):
14544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs = args[:]
14554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs[i] = args[i] + 1
14564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t2 = self.theclass(*newargs)   # this is larger than t1
14574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 < t2)
14584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 > t1)
14594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 <= t2)
14604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 >= t1)
14614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 != t2)
14624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 != t1)
14634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 == t2)
14644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 == t1)
14654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 > t2)
14664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 < t1)
14674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 >= t2)
14684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 <= t1)
14694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(cmp(t1, t2), -1)
14704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(cmp(t2, t1), 1)
14714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # A helper for timestamp constructor tests.
14744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def verify_field_equality(self, expected, got):
14754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(expected.tm_year, got.year)
14764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(expected.tm_mon, got.month)
14774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(expected.tm_mday, got.day)
14784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(expected.tm_hour, got.hour)
14794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(expected.tm_min, got.minute)
14804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(expected.tm_sec, got.second)
14814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_fromtimestamp(self):
14834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import time
14844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ts = time.time()
14864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = time.localtime(ts)
14874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        got = self.theclass.fromtimestamp(ts)
14884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.verify_field_equality(expected, got)
14894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_utcfromtimestamp(self):
14914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import time
14924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ts = time.time()
14944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = time.gmtime(ts)
14954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        got = self.theclass.utcfromtimestamp(ts)
14964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.verify_field_equality(expected, got)
14974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
14984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_microsecond_rounding(self):
14994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test whether fromtimestamp "rounds up" floats that are less
15004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # than one microsecond smaller than an integer.
15014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(self.theclass.fromtimestamp(0.9999999),
15024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         self.theclass.fromtimestamp(1))
15034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_insane_fromtimestamp(self):
15054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # It's possible that some platform maps time_t to double,
15064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # and that this test will fail there.  This test should
15074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # exempt such platforms (provided they return reasonable
15084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # results!).
15094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for insane in -1e200, 1e200:
15104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ValueError, self.theclass.fromtimestamp,
15114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              insane)
15124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_insane_utcfromtimestamp(self):
15144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # It's possible that some platform maps time_t to double,
15154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # and that this test will fail there.  This test should
15164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # exempt such platforms (provided they return reasonable
15174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # results!).
15184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for insane in -1e200, 1e200:
15194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(ValueError, self.theclass.utcfromtimestamp,
15204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              insane)
15214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps")
15224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_negative_float_fromtimestamp(self):
15234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # The result is tz-dependent; at least test that this doesn't
15244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # fail (like it did before bug 1646728 was fixed).
15254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass.fromtimestamp(-1.05)
15264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps")
15284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_negative_float_utcfromtimestamp(self):
15294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = self.theclass.utcfromtimestamp(-1.05)
15304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d, self.theclass(1969, 12, 31, 23, 59, 58, 950000))
15314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_utcnow(self):
15334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import time
15344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Call it a success if utcnow() and utcfromtimestamp() are within
15364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # a second of each other.
15374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tolerance = timedelta(seconds=1)
15384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for dummy in range(3):
15394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            from_now = self.theclass.utcnow()
15404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            from_timestamp = self.theclass.utcfromtimestamp(time.time())
15414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if abs(from_timestamp - from_now) <= tolerance:
15424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                break
15434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Else try again a few times.
15444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(abs(from_timestamp - from_now) <= tolerance)
15454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_strptime(self):
15474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import _strptime
15484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        string = '2004-12-01 13:02:47.197'
15504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        format = '%Y-%m-%d %H:%M:%S.%f'
15514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        result, frac = _strptime._strptime(string, format)
15524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = self.theclass(*(result[0:6]+(frac,)))
15534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        got = self.theclass.strptime(string, format)
15544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(expected, got)
15554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_more_timetuple(self):
15574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # This tests fields beyond those tested by the TestDate.test_timetuple.
15584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(2004, 12, 31, 6, 22, 33)
15594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.timetuple(), (2004, 12, 31, 6, 22, 33, 4, 366, -1))
15604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.timetuple(),
15614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         (t.year, t.month, t.day,
15624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          t.hour, t.minute, t.second,
15634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          t.weekday(),
15644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          t.toordinal() - date(t.year, 1, 1).toordinal() + 1,
15654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          -1))
15664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tt = t.timetuple()
15674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(tt.tm_year, t.year)
15684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(tt.tm_mon, t.month)
15694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(tt.tm_mday, t.day)
15704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(tt.tm_hour, t.hour)
15714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(tt.tm_min, t.minute)
15724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(tt.tm_sec, t.second)
15734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(tt.tm_wday, t.weekday())
15744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(tt.tm_yday, t.toordinal() -
15754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     date(t.year, 1, 1).toordinal() + 1)
15764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(tt.tm_isdst, -1)
15774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_more_strftime(self):
15794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # This tests fields beyond those tested by the TestDate.test_strftime.
15804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(2004, 12, 31, 6, 22, 33, 47)
15814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.strftime("%m %d %y %f %S %M %H %j"),
15824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                    "12 31 04 000047 33 22 06 366")
15834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_extract(self):
15854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = self.theclass(2002, 3, 4, 18, 45, 3, 1234)
15864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.date(), date(2002, 3, 4))
15874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.time(), time(18, 45, 3, 1234))
15884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_combine(self):
15904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = date(2002, 3, 4)
15914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = time(18, 45, 3, 1234)
15924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = self.theclass(2002, 3, 4, 18, 45, 3, 1234)
15934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        combine = self.theclass.combine
15944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = combine(d, t)
15954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt, expected)
15964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
15974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = combine(time=t, date=d)
15984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt, expected)
15994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d, dt.date())
16014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t, dt.time())
16024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt, combine(dt.date(), dt.time()))
16034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, combine) # need an arg
16054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, combine, d) # need two args
16064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, combine, t, d) # args reversed
16074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, combine, d, t, 1) # too many args
16084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, combine, "date", "time") # wrong types
16094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_replace(self):
16114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
16124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = [1, 2, 3, 4, 5, 6, 7]
16134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(*args)
16144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(base, base.replace())
16154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        i = 0
16174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for name, newval in (("year", 2),
16184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("month", 3),
16194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("day", 4),
16204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("hour", 5),
16214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("minute", 6),
16224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("second", 7),
16234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("microsecond", 8)):
16244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs = args[:]
16254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs[i] = newval
16264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            expected = cls(*newargs)
16274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = base.replace(**{name: newval})
16284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
16294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            i += 1
16304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Out of bounds.
16324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(2000, 2, 29)
16334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, year=2001)
16344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_astimezone(self):
16364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Pretty boring!  The TZ test is more interesting here.  astimezone()
16374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # simply can't be applied to a naive object.
16384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = self.theclass.now()
16394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = FixedOffset(44, "")
16404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, dt.astimezone) # not enough args
16414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, dt.astimezone, f, f) # too many args
16424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, dt.astimezone, dt) # arg wrong type
16434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, dt.astimezone, f) # naive
16444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, dt.astimezone, tz=f)  # naive
16454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class Bogus(tzinfo):
16474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): return None
16484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt): return timedelta(0)
16494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        bog = Bogus()
16504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, dt.astimezone, bog)   # naive
16514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class AlsoBogus(tzinfo):
16534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): return timedelta(0)
16544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt): return None
16554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        alsobog = AlsoBogus()
16564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, dt.astimezone, alsobog) # also naive
16574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_subclass_datetime(self):
16594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class C(self.theclass):
16614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            theAnswer = 42
16624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __new__(cls, *args, **kws):
16644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                temp = kws.copy()
16654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                extra = temp.pop('extra')
16664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                result = self.theclass.__new__(cls, *args, **temp)
16674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                result.extra = extra
16684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return result
16694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def newmeth(self, start):
16714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return start + self.year + self.month + self.second
16724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 2003, 4, 14, 12, 13, 41
16744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt1 = self.theclass(*args)
16764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = C(*args, **{'extra': 7})
16774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.__class__, C)
16794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.theAnswer, 42)
16804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.extra, 7)
16814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt1.toordinal(), dt2.toordinal())
16824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month +
16834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                          dt1.second - 7)
16844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass SubclassTime(time):
16864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    sub_var = 1
16874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestTime(HarmlessMixedComparison, unittest.TestCase):
16894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    theclass = time
16914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_basic_attributes(self):
16934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(12, 0)
16944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.hour, 12)
16954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.minute, 0)
16964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.second, 0)
16974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.microsecond, 0)
16984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
16994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_basic_attributes_nonzero(self):
17004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Make sure all attributes are non-zero so bugs in
17014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bit-shifting access show up.
17024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(12, 59, 59, 8000)
17034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.hour, 12)
17044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.minute, 59)
17054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.second, 59)
17064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.microsecond, 8000)
17074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_roundtrip(self):
17094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(1, 2, 3, 4)
17104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Verify t -> string -> time identity.
17124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = repr(t)
17134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(s.startswith('datetime.'))
17144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = s[9:]
17154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = eval(s)
17164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t, t2)
17174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Verify identity via reconstructing from pieces.
17194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass(t.hour, t.minute, t.second,
17204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           t.microsecond)
17214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t, t2)
17224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_comparing(self):
17244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = [1, 2, 3, 4]
17254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(*args)
17264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass(*args)
17274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 == t2)
17284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 <= t2)
17294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 >= t2)
17304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 != t2)
17314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 < t2)
17324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t1 > t2)
17334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmp(t1, t2), 0)
17344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmp(t2, t1), 0)
17354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in range(len(args)):
17374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs = args[:]
17384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs[i] = args[i] + 1
17394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t2 = self.theclass(*newargs)   # this is larger than t1
17404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 < t2)
17414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 > t1)
17424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 <= t2)
17434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 >= t1)
17444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t1 != t2)
17454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t2 != t1)
17464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 == t2)
17474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 == t1)
17484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 > t2)
17494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 < t1)
17504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t1 >= t2)
17514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(not t2 <= t1)
17524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(cmp(t1, t2), -1)
17534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(cmp(t2, t1), 1)
17544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for badarg in OTHERSTUFF:
17564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t1 == badarg, False)
17574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t1 != badarg, True)
17584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(badarg == t1, False)
17594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(badarg != t1, True)
17604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 <= badarg)
17624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 < badarg)
17634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 > badarg)
17644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: t1 >= badarg)
17654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg <= t1)
17664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg < t1)
17674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg > t1)
17684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, lambda: badarg >= t1)
17694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bad_constructor_arguments(self):
17714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad hours
17724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(0, 0)    # no exception
17734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(23, 0)   # no exception
17744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, -1, 0)
17754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 24, 0)
17764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad minutes
17774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(23, 0)    # no exception
17784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(23, 59)   # no exception
17794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 23, -1)
17804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 23, 60)
17814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad seconds
17824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(23, 59, 0)    # no exception
17834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(23, 59, 59)   # no exception
17844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 23, 59, -1)
17854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 23, 59, 60)
17864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # bad microseconds
17874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(23, 59, 59, 0)        # no exception
17884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.theclass(23, 59, 59, 999999)   # no exception
17894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 23, 59, 59, -1)
17904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, self.theclass, 23, 59, 59, 1000000)
17914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_hash_equality(self):
17934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = self.theclass(23, 30, 17)
17944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        e = self.theclass(23, 30, 17)
17954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d, e)
17964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(d), hash(e))
17974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
17984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic = {d: 1}
17994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic[e] = 2
18004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(dic), 1)
18014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[d], 2)
18024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[e], 2)
18034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = self.theclass(0,  5, 17)
18054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        e = self.theclass(0,  5, 17)
18064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(d, e)
18074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(d), hash(e))
18084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic = {d: 1}
18104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dic[e] = 2
18114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(dic), 1)
18124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[d], 2)
18134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dic[e], 2)
18144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_isoformat(self):
18164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(4, 5, 1, 123)
18174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), "04:05:01.000123")
18184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), str(t))
18194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass()
18214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), "00:00:00")
18224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), str(t))
18234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(microsecond=1)
18254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), "00:00:00.000001")
18264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), str(t))
18274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(microsecond=10)
18294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), "00:00:00.000010")
18304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), str(t))
18314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(microsecond=100)
18334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), "00:00:00.000100")
18344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), str(t))
18354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(microsecond=1000)
18374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), "00:00:00.001000")
18384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), str(t))
18394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(microsecond=10000)
18414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), "00:00:00.010000")
18424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), str(t))
18434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(microsecond=100000)
18454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), "00:00:00.100000")
18464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.isoformat(), str(t))
18474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_1653736(self):
18494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # verify it doesn't accept extra keyword arguments
18504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(second=1)
18514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t.isoformat, foo=3)
18524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_strftime(self):
18544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(1, 2, 3, 4)
18554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.strftime('%H %M %S %f'), "01 02 03 000004")
18564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A naive object replaces %z and %Z with empty strings.
18574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
18584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_format(self):
18604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(1, 2, 3, 4)
18614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.__format__(''), str(t))
18624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # check that a derived class's __str__() gets called
18644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class A(self.theclass):
18654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __str__(self):
18664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return 'A'
18674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = A(1, 2, 3, 4)
18684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.__format__(''), 'A')
18694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # check that a derived class's strftime gets called
18714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class B(self.theclass):
18724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def strftime(self, format_spec):
18734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return 'B'
18744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = B(1, 2, 3, 4)
18754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(b.__format__(''), str(t))
18764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for fmt in ['%H %M %S',
18784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    ]:
18794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(t.__format__(fmt), t.strftime(fmt))
18804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(a.__format__(fmt), t.strftime(fmt))
18814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(b.__format__(fmt), 'B')
18824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_str(self):
18844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(self.theclass(1, 2, 3, 4)), "01:02:03.000004")
18854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(self.theclass(10, 2, 3, 4000)), "10:02:03.004000")
18864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(self.theclass(0, 2, 3, 400000)), "00:02:03.400000")
18874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(self.theclass(12, 2, 3, 0)), "12:02:03")
18884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(self.theclass(23, 15, 0, 0)), "23:15:00")
18894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
18904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_repr(self):
18914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        name = 'datetime.' + self.theclass.__name__
18924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(self.theclass(1, 2, 3, 4)),
18934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         "%s(1, 2, 3, 4)" % name)
18944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(self.theclass(10, 2, 3, 4000)),
18954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         "%s(10, 2, 3, 4000)" % name)
18964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(self.theclass(0, 2, 3, 400000)),
18974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         "%s(0, 2, 3, 400000)" % name)
18984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(self.theclass(12, 2, 3, 0)),
18994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         "%s(12, 2, 3)" % name)
19004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(self.theclass(23, 15, 0, 0)),
19014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         "%s(23, 15)" % name)
19024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_resolution_info(self):
19044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(self.theclass.min, self.theclass)
19054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(self.theclass.max, self.theclass)
19064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(self.theclass.resolution, timedelta)
19074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(self.theclass.max > self.theclass.min)
19084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling(self):
19104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 20, 59, 16, 64**2
19114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = self.theclass(*args)
19124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
19134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
19144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
19154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
19164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling_subclass_time(self):
19184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 20, 59, 16, 64**2
19194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = SubclassTime(*args)
19204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
19214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
19224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
19234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
19244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bool(self):
19264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
19274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(cls(1))
19284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(cls(0, 1))
19294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(cls(0, 0, 1))
19304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(cls(0, 0, 0, 1))
19314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not cls(0))
19324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not cls())
19334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_replace(self):
19354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
19364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = [1, 2, 3, 4]
19374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(*args)
19384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(base, base.replace())
19394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        i = 0
19414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for name, newval in (("hour", 5),
19424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("minute", 6),
19434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("second", 7),
19444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("microsecond", 8)):
19454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs = args[:]
19464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs[i] = newval
19474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            expected = cls(*newargs)
19484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = base.replace(**{name: newval})
19494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
19504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            i += 1
19514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Out of bounds.
19534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(1)
19544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, hour=24)
19554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, minute=-1)
19564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, second=100)
19574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, microsecond=1000000)
19584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_subclass_time(self):
19604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class C(self.theclass):
19624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            theAnswer = 42
19634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __new__(cls, *args, **kws):
19654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                temp = kws.copy()
19664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                extra = temp.pop('extra')
19674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                result = self.theclass.__new__(cls, *args, **temp)
19684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                result.extra = extra
19694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return result
19704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def newmeth(self, start):
19724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return start + self.hour + self.second
19734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 4, 5, 6
19754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt1 = self.theclass(*args)
19774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = C(*args, **{'extra': 7})
19784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.__class__, C)
19804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.theAnswer, 42)
19814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.extra, 7)
19824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt1.isoformat(), dt2.isoformat())
19834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.second - 7)
19844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_backdoor_resistance(self):
19864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # see TestDate.test_backdoor_resistance().
19874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = '2:59.0'
19884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for hour_byte in ' ', '9', chr(24), '\xff':
19894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(TypeError, self.theclass,
19904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                         hour_byte + base[1:])
19914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# A mixin for classes with a tzinfo= argument.  Subclasses must define
19934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# theclass as a class atribute, and theclass(1, 1, 1, tzinfo=whatever)
19944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# must be legit (which is true for time and datetime).
19954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TZInfoBase:
19964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
19974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_argument_passing(self):
19984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
19994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A datetime passes itself on, a time passes None.
20004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class introspective(tzinfo):
20014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def tzname(self, dt):    return dt and "real" or "none"
20024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt):
20034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return timedelta(minutes = dt and 42 or -42)
20044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dst = utcoffset
20054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        obj = cls(1, 2, 3, tzinfo=introspective())
20074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = cls is time and "none" or "real"
20094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(obj.tzname(), expected)
20104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = timedelta(minutes=(cls is time and -42 or 42))
20124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(obj.utcoffset(), expected)
20134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(obj.dst(), expected)
20144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bad_tzinfo_classes(self):
20164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
20174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, cls, 1, 1, 1, tzinfo=12)
20184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class NiceTry(object):
20204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __init__(self): pass
20214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): pass
20224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, cls, 1, 1, 1, tzinfo=NiceTry)
20234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class BetterTry(tzinfo):
20254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __init__(self): pass
20264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): pass
20274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = BetterTry()
20284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(1, 1, 1, tzinfo=b)
20294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t.tzinfo is b)
20304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_utc_offset_out_of_bounds(self):
20324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class Edgy(tzinfo):
20334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __init__(self, offset):
20344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.offset = timedelta(minutes=offset)
20354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt):
20364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return self.offset
20374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
20394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for offset, legit in ((-1440, False),
20404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              (-1439, True),
20414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              (1439, True),
20424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              (1440, False)):
20434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if cls is time:
20444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                t = cls(1, 2, 3, tzinfo=Edgy(offset))
20454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            elif cls is datetime:
20464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                t = cls(6, 6, 6, 1, 2, 3, tzinfo=Edgy(offset))
20474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
20484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                assert 0, "impossible"
20494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if legit:
20504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                aofs = abs(offset)
20514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                h, m = divmod(aofs, 60)
20524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                tag = "%c%02d:%02d" % (offset < 0 and '-' or '+', h, m)
20534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if isinstance(t, datetime):
20544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    t = t.timetz()
20554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(str(t), "01:02:03" + tag)
20564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
20574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertRaises(ValueError, str, t)
20584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tzinfo_classes(self):
20604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
20614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class C1(tzinfo):
20624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): return None
20634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt): return None
20644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def tzname(self, dt): return None
20654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for t in (cls(1, 1, 1),
20664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  cls(1, 1, 1, tzinfo=None),
20674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  cls(1, 1, 1, tzinfo=C1())):
20684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t.utcoffset() is None)
20694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t.dst() is None)
20704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(t.tzname() is None)
20714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class C3(tzinfo):
20734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): return timedelta(minutes=-1439)
20744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt): return timedelta(minutes=1439)
20754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def tzname(self, dt): return "aname"
20764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(1, 1, 1, tzinfo=C3())
20774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.utcoffset(), timedelta(minutes=-1439))
20784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.dst(), timedelta(minutes=1439))
20794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tzname(), "aname")
20804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Wrong types.
20824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class C4(tzinfo):
20834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): return "aname"
20844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt): return 7
20854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def tzname(self, dt): return 0
20864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(1, 1, 1, tzinfo=C4())
20874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t.utcoffset)
20884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t.dst)
20894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t.tzname)
20904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Offset out of range.
20924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class C6(tzinfo):
20934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): return timedelta(hours=-24)
20944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt): return timedelta(hours=24)
20954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(1, 1, 1, tzinfo=C6())
20964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, t.utcoffset)
20974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, t.dst)
20984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
20994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Not a whole number of minutes.
21004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class C7(tzinfo):
21014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): return timedelta(seconds=61)
21024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt): return timedelta(microseconds=-81)
21034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(1, 1, 1, tzinfo=C7())
21044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, t.utcoffset)
21054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, t.dst)
21064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_aware_compare(self):
21084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
21094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure that utcoffset() gets ignored if the comparands have
21114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # the same tzinfo member.
21124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class OperandDependentOffset(tzinfo):
21134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, t):
21144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if t.minute < 10:
21154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    # d0 and d1 equal after adjustment
21164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    return timedelta(minutes=t.minute)
21174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                else:
21184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    # d2 off in the weeds
21194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    return timedelta(minutes=59)
21204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(8, 9, 10, tzinfo=OperandDependentOffset())
21224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d0 = base.replace(minute=3)
21234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d1 = base.replace(minute=9)
21244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d2 = base.replace(minute=11)
21254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for x in d0, d1, d2:
21264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for y in d0, d1, d2:
21274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                got = cmp(x, y)
21284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                expected = cmp(x.minute, y.minute)
21294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(got, expected)
21304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # However, if they're different members, uctoffset is not ignored.
21324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Note that a time can't actually have an operand-depedent offset,
21334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # though (and time.utcoffset() passes None to tzinfo.utcoffset()),
21344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # so skip this test for time.
21354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if cls is not time:
21364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d0 = base.replace(minute=3, tzinfo=OperandDependentOffset())
21374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d1 = base.replace(minute=9, tzinfo=OperandDependentOffset())
21384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d2 = base.replace(minute=11, tzinfo=OperandDependentOffset())
21394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for x in d0, d1, d2:
21404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                for y in d0, d1, d2:
21414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    got = cmp(x, y)
21424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    if (x is d0 or x is d1) and (y is d0 or y is d1):
21434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        expected = 0
21444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    elif x is y is d2:
21454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        expected = 0
21464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    elif x is d2:
21474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        expected = -1
21484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    else:
21494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        assert y is d2
21504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        expected = 1
21514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    self.assertEqual(got, expected)
21524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Testing time objects with a non-None tzinfo.
21554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase):
21564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    theclass = time
21574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_empty(self):
21594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass()
21604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.hour, 0)
21614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.minute, 0)
21624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.second, 0)
21634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.microsecond, 0)
21644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t.tzinfo is None)
21654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_zones(self):
21674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        est = FixedOffset(-300, "EST", 1)
21684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        utc = FixedOffset(0, "UTC", -2)
21694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        met = FixedOffset(60, "MET", 3)
21704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = time( 7, 47, tzinfo=est)
21714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = time(12, 47, tzinfo=utc)
21724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t3 = time(13, 47, tzinfo=met)
21734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t4 = time(microsecond=40)
21744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t5 = time(microsecond=40, tzinfo=utc)
21754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.tzinfo, est)
21774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.tzinfo, utc)
21784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.tzinfo, met)
21794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t4.tzinfo is None)
21804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t5.tzinfo, utc)
21814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.utcoffset(), timedelta(minutes=-300))
21834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.utcoffset(), timedelta(minutes=0))
21844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.utcoffset(), timedelta(minutes=60))
21854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t4.utcoffset() is None)
21864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t1.utcoffset, "no args")
21874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.tzname(), "EST")
21894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.tzname(), "UTC")
21904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.tzname(), "MET")
21914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t4.tzname() is None)
21924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t1.tzname, "no args")
21934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
21944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.dst(), timedelta(minutes=1))
21954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.dst(), timedelta(minutes=-2))
21964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.dst(), timedelta(minutes=3))
21974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t4.dst() is None)
21984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t1.dst, "no args")
21994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(t1), hash(t2))
22014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(t1), hash(t3))
22024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(t2), hash(t3))
22034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
22054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t3)
22064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2, t3)
22074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: t4 == t5) # mixed tz-aware & naive
22084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: t4 < t5) # mixed tz-aware & naive
22094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: t5 < t4) # mixed tz-aware & naive
22104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t1), "07:47:00-05:00")
22124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t2), "12:47:00+00:00")
22134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t3), "13:47:00+01:00")
22144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t4), "00:00:00.000040")
22154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t5), "00:00:00.000040+00:00")
22164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.isoformat(), "07:47:00-05:00")
22184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.isoformat(), "12:47:00+00:00")
22194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.isoformat(), "13:47:00+01:00")
22204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t4.isoformat(), "00:00:00.000040")
22214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t5.isoformat(), "00:00:00.000040+00:00")
22224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = 'datetime.time'
22244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(t1), d + "(7, 47, tzinfo=est)")
22254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(t2), d + "(12, 47, tzinfo=utc)")
22264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(t3), d + "(13, 47, tzinfo=met)")
22274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(t4), d + "(0, 0, 0, 40)")
22284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(t5), d + "(0, 0, 0, 40, tzinfo=utc)")
22294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.strftime("%H:%M:%S %%Z=%Z %%z=%z"),
22314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     "07:47:00 %Z=EST %z=-0500")
22324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.strftime("%H:%M:%S %Z %z"), "12:47:00 UTC +0000")
22334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.strftime("%H:%M:%S %Z %z"), "13:47:00 MET +0100")
22344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        yuck = FixedOffset(-1439, "%z %Z %%z%%Z")
22364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = time(23, 59, tzinfo=yuck)
22374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.strftime("%H:%M %%Z='%Z' %%z='%z'"),
22384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     "23:59 %Z='%z %Z %%z%%Z' %z='-2359'")
22394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Check that an invalid tzname result raises an exception.
22414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class Badtzname(tzinfo):
22424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def tzname(self, dt): return 42
22434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = time(2, 3, 4, tzinfo=Badtzname())
22444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.strftime("%H:%M:%S"), "02:03:04")
22454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, t.strftime, "%Z")
22464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_hash_edge_cases(self):
22484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Offsets that overflow a basic time.
22494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(0, 1, 2, 3, tzinfo=FixedOffset(1439, ""))
22504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass(0, 0, 2, 3, tzinfo=FixedOffset(1438, ""))
22514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(t1), hash(t2))
22524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(23, 58, 6, 100, tzinfo=FixedOffset(-1000, ""))
22544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass(23, 48, 6, 100, tzinfo=FixedOffset(-1010, ""))
22554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(t1), hash(t2))
22564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling(self):
22584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try one without a tzinfo.
22594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 20, 59, 16, 64**2
22604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = self.theclass(*args)
22614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
22624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
22634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
22644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
22654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try one with a tzinfo.
22674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tinfo = PicklableFixedOffset(-300, 'cookie')
22684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = self.theclass(5, 6, 7, tzinfo=tinfo)
22694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
22704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
22714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
22724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
22734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertIsInstance(derived.tzinfo, PicklableFixedOffset)
22744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(derived.utcoffset(), timedelta(minutes=-300))
22754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(derived.tzname(), 'cookie')
22764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_more_bool(self):
22784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test cases with non-None tzinfo.
22794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
22804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(0, tzinfo=FixedOffset(-300, ""))
22824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t)
22834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(5, tzinfo=FixedOffset(-300, ""))
22854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t)
22864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(5, tzinfo=FixedOffset(300, ""))
22884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t)
22894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(23, 59, tzinfo=FixedOffset(23*60 + 59, ""))
22914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not t)
22924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Mostly ensuring this doesn't overflow internally.
22944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(0, tzinfo=FixedOffset(23*60 + 59, ""))
22954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t)
22964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
22974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # But this should yield a value error -- the utcoffset is bogus.
22984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(0, tzinfo=FixedOffset(24*60, ""))
22994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, lambda: bool(t))
23004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Likewise.
23024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = cls(0, tzinfo=FixedOffset(-24*60, ""))
23034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, lambda: bool(t))
23044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_replace(self):
23064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
23074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        z100 = FixedOffset(100, "+100")
23084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        zm200 = FixedOffset(timedelta(minutes=-200), "-200")
23094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = [1, 2, 3, 4, z100]
23104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(*args)
23114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(base, base.replace())
23124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        i = 0
23144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for name, newval in (("hour", 5),
23154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("minute", 6),
23164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("second", 7),
23174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("microsecond", 8),
23184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("tzinfo", zm200)):
23194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs = args[:]
23204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs[i] = newval
23214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            expected = cls(*newargs)
23224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = base.replace(**{name: newval})
23234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
23244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            i += 1
23254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure we can get rid of a tzinfo.
23274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(base.tzname(), "+100")
23284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base2 = base.replace(tzinfo=None)
23294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(base2.tzinfo is None)
23304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(base2.tzname() is None)
23314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure we can add one.
23334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base3 = base2.replace(tzinfo=z100)
23344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(base, base3)
23354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(base.tzinfo is base3.tzinfo)
23364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Out of bounds.
23384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(1)
23394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, hour=24)
23404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, minute=-1)
23414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, second=100)
23424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, microsecond=1000000)
23434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_mixed_compare(self):
23454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = time(1, 2, 3)
23464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = time(1, 2, 3)
23474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
23484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = t2.replace(tzinfo=None)
23494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
23504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = t2.replace(tzinfo=FixedOffset(None, ""))
23514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
23524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = t2.replace(tzinfo=FixedOffset(0, ""))
23534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: t1 == t2)
23544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # In time w/ identical tzinfo objects, utcoffset is ignored.
23564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class Varies(tzinfo):
23574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __init__(self):
23584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.offset = timedelta(minutes=22)
23594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, t):
23604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.offset += timedelta(minutes=1)
23614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return self.offset
23624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        v = Varies()
23644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = t2.replace(tzinfo=v)
23654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = t2.replace(tzinfo=v)
23664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.utcoffset(), timedelta(minutes=23))
23674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.utcoffset(), timedelta(minutes=24))
23684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
23694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # But if they're not identical, it isn't ignored.
23714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = t2.replace(tzinfo=Varies())
23724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 < t2)  # t1's offset counter still going up
23734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_subclass_timetz(self):
23754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class C(self.theclass):
23774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            theAnswer = 42
23784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __new__(cls, *args, **kws):
23804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                temp = kws.copy()
23814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                extra = temp.pop('extra')
23824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                result = self.theclass.__new__(cls, *args, **temp)
23834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                result.extra = extra
23844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return result
23854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def newmeth(self, start):
23874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return start + self.hour + self.second
23884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 4, 5, 6, 500, FixedOffset(-300, "EST", 1)
23904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt1 = self.theclass(*args)
23924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = C(*args, **{'extra': 7})
23934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
23944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.__class__, C)
23954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.theAnswer, 42)
23964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.extra, 7)
23974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt1.utcoffset(), dt2.utcoffset())
23984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.second - 7)
23994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Testing datetime objects with a non-None tzinfo.
24024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestDateTimeTZ(TestDateTime, TZInfoBase, unittest.TestCase):
24044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    theclass = datetime
24054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_trivial(self):
24074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = self.theclass(1, 2, 3, 4, 5, 6, 7)
24084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.year, 1)
24094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.month, 2)
24104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.day, 3)
24114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.hour, 4)
24124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.minute, 5)
24134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.second, 6)
24144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.microsecond, 7)
24154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.tzinfo, None)
24164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_even_more_compare(self):
24184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # The test_compare() and test_more_compare() inherited from TestDate
24194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # and TestDateTime covered non-tzinfo cases.
24204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Smallest possible after UTC adjustment.
24224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(1, 1, 1, tzinfo=FixedOffset(1439, ""))
24234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Largest possible after UTC adjustment.
24244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999999,
24254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           tzinfo=FixedOffset(-1439, ""))
24264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Make sure those compare correctly, and w/o overflow.
24284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 < t2)
24294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 != t2)
24304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t2 > t1)
24314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 == t1)
24334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t2 == t2)
24344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Equal afer adjustment.
24364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(1, ""))
24374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass(2, 1, 1, 3, 13, tzinfo=FixedOffset(3*60+13+2, ""))
24384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
24394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Change t1 not to subtract a minute, and t1 should be larger.
24414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(0, ""))
24424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 > t2)
24434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Change t1 to subtract 2 minutes, and t1 should be smaller.
24454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(2, ""))
24464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 < t2)
24474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Back to the original t1, but make seconds resolve it.
24494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(1, ""),
24504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           second=1)
24514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 > t2)
24524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Likewise, but make microseconds resolve it.
24544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(1, ""),
24554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                           microsecond=1)
24564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 > t2)
24574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Make t2 naive and it should fail.
24594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass.min
24604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: t1 == t2)
24614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2, t2)
24624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # It's also naive if it has tzinfo but tzinfo.utcoffset() is None.
24644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class Naive(tzinfo):
24654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): return None
24664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass(5, 6, 7, tzinfo=Naive())
24674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: t1 == t2)
24684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2, t2)
24694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # OTOH, it's OK to compare two of these mixing the two ways of being
24714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # naive.
24724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(5, 6, 7)
24734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
24744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try a bogus uctoffset.
24764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class Bogus(tzinfo):
24774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt):
24784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return timedelta(minutes=1440) # out of bounds
24794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = self.theclass(2, 2, 2, tzinfo=Bogus())
24804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = self.theclass(2, 2, 2, tzinfo=FixedOffset(0, ""))
24814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, lambda: t1 == t2)
24824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_pickling(self):
24844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try one without a tzinfo.
24854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 6, 7, 23, 20, 59, 1, 64**2
24864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = self.theclass(*args)
24874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
24884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
24894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
24904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
24914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
24924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try one with a tzinfo.
24934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tinfo = PicklableFixedOffset(-300, 'cookie')
24944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig = self.theclass(*args, **{'tzinfo': tinfo})
24954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        derived = self.theclass(1, 1, 1, tzinfo=FixedOffset(0, "", 0))
24964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for pickler, unpickler, proto in pickle_choices:
24974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            green = pickler.dumps(orig, proto)
24984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            derived = unpickler.loads(green)
24994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(orig, derived)
25004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertIsInstance(derived.tzinfo, PicklableFixedOffset)
25014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(derived.utcoffset(), timedelta(minutes=-300))
25024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(derived.tzname(), 'cookie')
25034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_extreme_hashes(self):
25054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # If an attempt is made to hash these via subtracting the offset
25064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # then hashing a datetime object, OverflowError results.  The
25074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Python implementation used to blow up here.
25084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(1, 1, 1, tzinfo=FixedOffset(1439, ""))
25094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        hash(t)
25104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999999,
25114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          tzinfo=FixedOffset(-1439, ""))
25124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        hash(t)
25134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # OTOH, an OOB offset should blow up.
25154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.theclass(5, 5, 5, tzinfo=FixedOffset(-1440, ""))
25164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, hash, t)
25174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_zones(self):
25194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        est = FixedOffset(-300, "EST")
25204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        utc = FixedOffset(0, "UTC")
25214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        met = FixedOffset(60, "MET")
25224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = datetime(2002, 3, 19,  7, 47, tzinfo=est)
25234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = datetime(2002, 3, 19, 12, 47, tzinfo=utc)
25244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t3 = datetime(2002, 3, 19, 13, 47, tzinfo=met)
25254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.tzinfo, est)
25264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.tzinfo, utc)
25274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.tzinfo, met)
25284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.utcoffset(), timedelta(minutes=-300))
25294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.utcoffset(), timedelta(minutes=0))
25304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.utcoffset(), timedelta(minutes=60))
25314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.tzname(), "EST")
25324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.tzname(), "UTC")
25334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t3.tzname(), "MET")
25344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(t1), hash(t2))
25354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(t1), hash(t3))
25364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(hash(t2), hash(t3))
25374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
25384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t3)
25394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2, t3)
25404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t1), "2002-03-19 07:47:00-05:00")
25414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t2), "2002-03-19 12:47:00+00:00")
25424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t3), "2002-03-19 13:47:00+01:00")
25434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = 'datetime.datetime(2002, 3, 19, '
25444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(t1), d + "7, 47, tzinfo=est)")
25454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(t2), d + "12, 47, tzinfo=utc)")
25464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(t3), d + "13, 47, tzinfo=met)")
25474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_combine(self):
25494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        met = FixedOffset(60, "MET")
25504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = date(2002, 3, 4)
25514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tz = time(18, 45, 3, 1234, tzinfo=met)
25524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = datetime.combine(d, tz)
25534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt, datetime(2002, 3, 4, 18, 45, 3, 1234,
25544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                        tzinfo=met))
25554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_extract(self):
25574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        met = FixedOffset(60, "MET")
25584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = self.theclass(2002, 3, 4, 18, 45, 3, 1234, tzinfo=met)
25594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.date(), date(2002, 3, 4))
25604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.time(), time(18, 45, 3, 1234))
25614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.timetz(), time(18, 45, 3, 1234, tzinfo=met))
25624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tz_aware_arithmetic(self):
25644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import random
25654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        now = self.theclass.now()
25674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tz55 = FixedOffset(-330, "west 5:30")
25684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        timeaware = now.time().replace(tzinfo=tz55)
25694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        nowaware = self.theclass.combine(now.date(), timeaware)
25704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(nowaware.tzinfo is tz55)
25714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(nowaware.timetz(), timeaware)
25724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Can't mix aware and non-aware.
25744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: now - nowaware)
25754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: nowaware - now)
25764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # And adding datetime's doesn't make sense, aware or not.
25784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: now + nowaware)
25794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: nowaware + now)
25804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: nowaware + nowaware)
25814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Subtracting should yield 0.
25834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(now - now, timedelta(0))
25844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(nowaware - nowaware, timedelta(0))
25854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Adding a delta should preserve tzinfo.
25874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        delta = timedelta(weeks=1, minutes=12, microseconds=5678)
25884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        nowawareplus = nowaware + delta
25894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(nowaware.tzinfo is tz55)
25904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        nowawareplus2 = delta + nowaware
25914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(nowawareplus2.tzinfo is tz55)
25924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(nowawareplus, nowawareplus2)
25934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
25944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # that - delta should be what we started with, and that - what we
25954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # started with should be delta.
25964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        diff = nowawareplus - delta
25974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(diff.tzinfo is tz55)
25984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(nowaware, diff)
25994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: delta - nowawareplus)
26004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(nowawareplus - nowaware, delta)
26014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
26024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Make up a random timezone.
26034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tzr = FixedOffset(random.randrange(-1439, 1440), "randomtimezone")
26044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Attach it to nowawareplus.
26054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        nowawareplus = nowawareplus.replace(tzinfo=tzr)
26064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(nowawareplus.tzinfo is tzr)
26074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Make sure the difference takes the timezone adjustments into account.
26084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        got = nowaware - nowawareplus
26094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Expected:  (nowaware base - nowaware offset) -
26104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #            (nowawareplus base - nowawareplus offset) =
26114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #            (nowaware base - nowawareplus base) +
26124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #            (nowawareplus offset - nowaware offset) =
26134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #            -delta + nowawareplus offset - nowaware offset
26144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = nowawareplus.utcoffset() - nowaware.utcoffset() - delta
26154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(got, expected)
26164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
26174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try max possible difference.
26184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        min = self.theclass(1, 1, 1, tzinfo=FixedOffset(1439, "min"))
26194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        max = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999999,
26204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                            tzinfo=FixedOffset(-1439, "max"))
26214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        maxdiff = max - min
26224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(maxdiff, self.theclass.max - self.theclass.min +
26234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                  timedelta(minutes=2*1439))
26244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
26254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tzinfo_now(self):
26264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        meth = self.theclass.now
26274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up).
26284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = meth()
26294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try with and without naming the keyword.
26304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        off42 = FixedOffset(42, "42")
26314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        another = meth(off42)
26324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        again = meth(tz=off42)
26334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(another.tzinfo is again.tzinfo)
26344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(another.utcoffset(), timedelta(minutes=42))
26354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Bad argument with and w/o naming the keyword.
26364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, 16)
26374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, tzinfo=16)
26384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Bad keyword name.
26394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, tinfo=off42)
26404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Too many args.
26414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, off42, off42)
26424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
26434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # We don't know which time zone we're in, and don't have a tzinfo
26444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # class to represent it, so seeing whether a tz argument actually
26454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # does a conversion is tricky.
26464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        weirdtz = FixedOffset(timedelta(hours=15, minutes=58), "weirdtz", 0)
26474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        utc = FixedOffset(0, "utc", 0)
26484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for dummy in range(3):
26494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            now = datetime.now(weirdtz)
26504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(now.tzinfo is weirdtz)
26514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            utcnow = datetime.utcnow().replace(tzinfo=utc)
26524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            now2 = utcnow.astimezone(weirdtz)
26534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if abs(now - now2) < timedelta(seconds=30):
26544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                break
26554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Else the code is broken, or more than 30 seconds passed between
26564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # calls; assuming the latter, just try again.
26574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
26584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Three strikes and we're out.
26594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("utcnow(), now(tz), or astimezone() may be broken")
26604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
26614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tzinfo_fromtimestamp(self):
26624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import time
26634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        meth = self.theclass.fromtimestamp
26644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ts = time.time()
26654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up).
26664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = meth(ts)
26674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try with and without naming the keyword.
26684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        off42 = FixedOffset(42, "42")
26694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        another = meth(ts, off42)
26704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        again = meth(ts, tz=off42)
26714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(another.tzinfo is again.tzinfo)
26724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(another.utcoffset(), timedelta(minutes=42))
26734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Bad argument with and w/o naming the keyword.
26744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, ts, 16)
26754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, ts, tzinfo=16)
26764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Bad keyword name.
26774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, ts, tinfo=off42)
26784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Too many args.
26794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, ts, off42, off42)
26804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Too few args.
26814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth)
26824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
26834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try to make sure tz= actually does some conversion.
26844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        timestamp = 1000000000
26854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        utcdatetime = datetime.utcfromtimestamp(timestamp)
26864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # In POSIX (epoch 1970), that's 2001-09-09 01:46:40 UTC, give or take.
26874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # But on some flavor of Mac, it's nowhere near that.  So we can't have
26884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # any idea here what time that actually is, we can only test that
26894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # relative changes match.
26904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        utcoffset = timedelta(hours=-15, minutes=39) # arbitrary, but not zero
26914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tz = FixedOffset(utcoffset, "tz", 0)
26924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = utcdatetime + utcoffset
26934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        got = datetime.fromtimestamp(timestamp, tz)
26944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(expected, got.replace(tzinfo=None))
26954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
26964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tzinfo_utcnow(self):
26974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        meth = self.theclass.utcnow
26984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up).
26994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = meth()
27004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try with and without naming the keyword; for whatever reason,
27014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # utcnow() doesn't accept a tzinfo argument.
27024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        off42 = FixedOffset(42, "42")
27034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, off42)
27044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, tzinfo=off42)
27054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tzinfo_utcfromtimestamp(self):
27074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import time
27084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        meth = self.theclass.utcfromtimestamp
27094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ts = time.time()
27104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up).
27114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = meth(ts)
27124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Try with and without naming the keyword; for whatever reason,
27134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # utcfromtimestamp() doesn't accept a tzinfo argument.
27144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        off42 = FixedOffset(42, "42")
27154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, ts, off42)
27164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, meth, ts, tzinfo=off42)
27174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tzinfo_timetuple(self):
27194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # TestDateTime tested most of this.  datetime adds a twist to the
27204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # DST flag.
27214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class DST(tzinfo):
27224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __init__(self, dstvalue):
27234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if isinstance(dstvalue, int):
27244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    dstvalue = timedelta(minutes=dstvalue)
27254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.dstvalue = dstvalue
27264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt):
27274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return self.dstvalue
27284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
27304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for dstvalue, flag in (-33, 1), (33, 1), (0, 0), (None, -1):
27314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = cls(1, 1, 1, 10, 20, 30, 40, tzinfo=DST(dstvalue))
27324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t = d.timetuple()
27334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(1, t.tm_year)
27344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(1, t.tm_mon)
27354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(1, t.tm_mday)
27364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(10, t.tm_hour)
27374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(20, t.tm_min)
27384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(30, t.tm_sec)
27394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(0, t.tm_wday)
27404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(1, t.tm_yday)
27414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(flag, t.tm_isdst)
27424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # dst() returns wrong type.
27444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, cls(1, 1, 1, tzinfo=DST("x")).timetuple)
27454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # dst() at the edge.
27474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cls(1,1,1, tzinfo=DST(1439)).timetuple().tm_isdst, 1)
27484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cls(1,1,1, tzinfo=DST(-1439)).timetuple().tm_isdst, 1)
27494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # dst() out of range.
27514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, cls(1,1,1, tzinfo=DST(1440)).timetuple)
27524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, cls(1,1,1, tzinfo=DST(-1440)).timetuple)
27534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_utctimetuple(self):
27554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class DST(tzinfo):
27564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __init__(self, dstvalue):
27574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if isinstance(dstvalue, int):
27584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    dstvalue = timedelta(minutes=dstvalue)
27594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.dstvalue = dstvalue
27604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt):
27614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return self.dstvalue
27624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
27644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # This can't work:  DST didn't implement utcoffset.
27654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(NotImplementedError,
27664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          cls(1, 1, 1, tzinfo=DST(0)).utcoffset)
27674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class UOFS(DST):
27694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __init__(self, uofs, dofs=None):
27704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                DST.__init__(self, dofs)
27714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.uofs = timedelta(minutes=uofs)
27724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt):
27734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return self.uofs
27744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure tm_isdst is 0 regardless of what dst() says:  DST is never
27764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # in effect for a UTC time.
27774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for dstvalue in -33, 33, 0, None:
27784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=UOFS(-53, dstvalue))
27794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            t = d.utctimetuple()
27804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.year, t.tm_year)
27814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.month, t.tm_mon)
27824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.day, t.tm_mday)
27834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(11, t.tm_hour) # 20mm + 53mm = 1hn + 13mm
27844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(13, t.tm_min)
27854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.second, t.tm_sec)
27864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.weekday(), t.tm_wday)
27874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(d.toordinal() - date(1, 1, 1).toordinal() + 1,
27884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             t.tm_yday)
27894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(0, t.tm_isdst)
27904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
27914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # At the edges, UTC adjustment can normalize into years out-of-range
27924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # for a datetime object.  Ensure that a correct timetuple is
27934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # created anyway.
27944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tiny = cls(MINYEAR, 1, 1, 0, 0, 37, tzinfo=UOFS(1439))
27954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # That goes back 1 minute less than a full day.
27964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = tiny.utctimetuple()
27974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_year, MINYEAR-1)
27984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_mon, 12)
27994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_mday, 31)
28004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_hour, 0)
28014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_min, 1)
28024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_sec, 37)
28034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_yday, 366)    # "year 0" is a leap year
28044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_isdst, 0)
28054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        huge = cls(MAXYEAR, 12, 31, 23, 59, 37, 999999, tzinfo=UOFS(-1439))
28074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # That goes forward 1 minute less than a full day.
28084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = huge.utctimetuple()
28094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_year, MAXYEAR+1)
28104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_mon, 1)
28114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_mday, 1)
28124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_hour, 23)
28134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_min, 58)
28144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_sec, 37)
28154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_yday, 1)
28164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t.tm_isdst, 0)
28174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tzinfo_isoformat(self):
28194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        zero = FixedOffset(0, "+00:00")
28204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        plus = FixedOffset(220, "+03:40")
28214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        minus = FixedOffset(-231, "-03:51")
28224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        unknown = FixedOffset(None, "")
28234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
28254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        datestr = '0001-02-03'
28264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for ofs in None, zero, plus, minus, unknown:
28274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for us in 0, 987001:
28284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                d = cls(1, 2, 3, 4, 5, 59, us, tzinfo=ofs)
28294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                timestr = '04:05:59' + (us and '.987001' or '')
28304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                ofsstr = ofs is not None and d.tzname() or ''
28314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                tailstr = timestr + ofsstr
28324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                iso = d.isoformat()
28334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(iso, datestr + 'T' + tailstr)
28344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(iso, d.isoformat('T'))
28354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(d.isoformat('k'), datestr + 'k' + tailstr)
28364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(str(d), datestr + ' ' + tailstr)
28374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_replace(self):
28394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
28404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        z100 = FixedOffset(100, "+100")
28414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        zm200 = FixedOffset(timedelta(minutes=-200), "-200")
28424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = [1, 2, 3, 4, 5, 6, 7, z100]
28434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(*args)
28444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(base, base.replace())
28454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        i = 0
28474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for name, newval in (("year", 2),
28484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("month", 3),
28494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("day", 4),
28504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("hour", 5),
28514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("minute", 6),
28524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("second", 7),
28534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("microsecond", 8),
28544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             ("tzinfo", zm200)):
28554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs = args[:]
28564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            newargs[i] = newval
28574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            expected = cls(*newargs)
28584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = base.replace(**{name: newval})
28594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
28604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            i += 1
28614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure we can get rid of a tzinfo.
28634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(base.tzname(), "+100")
28644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base2 = base.replace(tzinfo=None)
28654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(base2.tzinfo is None)
28664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(base2.tzname() is None)
28674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure we can add one.
28694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base3 = base2.replace(tzinfo=z100)
28704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(base, base3)
28714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(base.tzinfo is base3.tzinfo)
28724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Out of bounds.
28744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(2000, 2, 29)
28754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, base.replace, year=2001)
28764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_more_astimezone(self):
28784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # The inherited test_astimezone covered some trivial and error cases.
28794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        fnone = FixedOffset(None, "None")
28804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f44m = FixedOffset(44, "44")
28814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        fm5h = FixedOffset(-timedelta(hours=5), "m300")
28824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = self.theclass.now(tz=f44m)
28844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(dt.tzinfo is f44m)
28854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Replacing with degenerate tzinfo raises an exception.
28864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, dt.astimezone, fnone)
28874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ditto with None tz.
28884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, dt.astimezone, None)
28894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Replacing with same tzinfo makes no change.
28904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        x = dt.astimezone(dt.tzinfo)
28914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(x.tzinfo is f44m)
28924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(x.date(), dt.date())
28934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(x.time(), dt.time())
28944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
28954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Replacing with different tzinfo does adjust.
28964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        got = dt.astimezone(fm5h)
28974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(got.tzinfo is fm5h)
28984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(got.utcoffset(), timedelta(hours=-5))
28994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = dt - dt.utcoffset()  # in effect, convert to UTC
29004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected += fm5h.utcoffset(dt)  # and from there to local time
29014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = expected.replace(tzinfo=fm5h) # and attach new tzinfo
29024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(got.date(), expected.date())
29034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(got.time(), expected.time())
29044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(got.timetz(), expected.timetz())
29054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(got.tzinfo is expected.tzinfo)
29064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(got, expected)
29074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_aware_subtract(self):
29094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cls = self.theclass
29104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ensure that utcoffset() is ignored when the operands have the
29124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # same tzinfo member.
29134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class OperandDependentOffset(tzinfo):
29144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, t):
29154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if t.minute < 10:
29164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    # d0 and d1 equal after adjustment
29174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    return timedelta(minutes=t.minute)
29184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                else:
29194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    # d2 off in the weeds
29204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    return timedelta(minutes=59)
29214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(8, 9, 10, 11, 12, 13, 14, tzinfo=OperandDependentOffset())
29234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d0 = base.replace(minute=3)
29244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d1 = base.replace(minute=9)
29254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d2 = base.replace(minute=11)
29264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for x in d0, d1, d2:
29274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for y in d0, d1, d2:
29284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                got = x - y
29294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                expected = timedelta(minutes=x.minute - y.minute)
29304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(got, expected)
29314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # OTOH, if the tzinfo members are distinct, utcoffsets aren't
29334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # ignored.
29344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        base = cls(8, 9, 10, 11, 12, 13, 14)
29354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d0 = base.replace(minute=3, tzinfo=OperandDependentOffset())
29364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d1 = base.replace(minute=9, tzinfo=OperandDependentOffset())
29374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d2 = base.replace(minute=11, tzinfo=OperandDependentOffset())
29384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for x in d0, d1, d2:
29394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for y in d0, d1, d2:
29404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                got = x - y
29414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                if (x is d0 or x is d1) and (y is d0 or y is d1):
29424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    expected = timedelta(0)
29434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                elif x is y is d2:
29444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    expected = timedelta(0)
29454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                elif x is d2:
29464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    expected = timedelta(minutes=(11-59)-0)
29474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                else:
29484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    assert y is d2
29494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    expected = timedelta(minutes=0-(11-59))
29504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(got, expected)
29514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_mixed_compare(self):
29534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = datetime(1, 2, 3, 4, 5, 6, 7)
29544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = datetime(1, 2, 3, 4, 5, 6, 7)
29554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
29564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = t2.replace(tzinfo=None)
29574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
29584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = t2.replace(tzinfo=FixedOffset(None, ""))
29594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
29604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = t2.replace(tzinfo=FixedOffset(0, ""))
29614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: t1 == t2)
29624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # In datetime w/ identical tzinfo objects, utcoffset is ignored.
29644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class Varies(tzinfo):
29654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __init__(self):
29664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.offset = timedelta(minutes=22)
29674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, t):
29684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.offset += timedelta(minutes=1)
29694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return self.offset
29704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        v = Varies()
29724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = t2.replace(tzinfo=v)
29734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = t2.replace(tzinfo=v)
29744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1.utcoffset(), timedelta(minutes=23))
29754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2.utcoffset(), timedelta(minutes=24))
29764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, t2)
29774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # But if they're not identical, it isn't ignored.
29794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = t2.replace(tzinfo=Varies())
29804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(t1 < t2)  # t1's offset counter still going up
29814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_subclass_datetimetz(self):
29834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class C(self.theclass):
29854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            theAnswer = 42
29864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def __new__(cls, *args, **kws):
29884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                temp = kws.copy()
29894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                extra = temp.pop('extra')
29904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                result = self.theclass.__new__(cls, *args, **temp)
29914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                result.extra = extra
29924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return result
29934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def newmeth(self, start):
29954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return start + self.hour + self.year
29964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        args = 2002, 12, 31, 4, 5, 6, 500, FixedOffset(-300, "EST", 1)
29984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
29994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt1 = self.theclass(*args)
30004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt2 = C(*args, **{'extra': 7})
30014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.__class__, C)
30034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.theAnswer, 42)
30044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.extra, 7)
30054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt1.utcoffset(), dt2.utcoffset())
30064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.year - 7)
30074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Pain to set up DST-aware tzinfo classes.
30094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef first_sunday_on_or_after(dt):
30114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    days_to_go = 6 - dt.weekday()
30124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if days_to_go:
30134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt += timedelta(days_to_go)
30144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return dt
30154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmZERO = timedelta(0)
30174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmHOUR = timedelta(hours=1)
30184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDAY = timedelta(days=1)
30194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# In the US, DST starts at 2am (standard time) on the first Sunday in April.
30204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDSTSTART = datetime(1, 4, 1, 2)
30214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# and ends at 2am (DST time; 1am standard time) on the last Sunday of Oct,
30224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# which is the first Sunday on or after Oct 25.  Because we view 1:MM as
30234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# being standard time on that day, there is no spelling in local time of
30244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# the last hour of DST (that's 1:MM DST, but 1:MM is taken as standard time).
30254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDSTEND = datetime(1, 10, 25, 1)
30264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass USTimeZone(tzinfo):
30284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __init__(self, hours, reprname, stdname, dstname):
30304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.stdoffset = timedelta(hours=hours)
30314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.reprname = reprname
30324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.stdname = stdname
30334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.dstname = dstname
30344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __repr__(self):
30364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.reprname
30374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tzname(self, dt):
30394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if self.dst(dt):
30404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return self.dstname
30414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
30424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return self.stdname
30434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def utcoffset(self, dt):
30454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.stdoffset + self.dst(dt)
30464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def dst(self, dt):
30484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if dt is None or dt.tzinfo is None:
30494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # An exception instead may be sensible here, in one or more of
30504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # the cases.
30514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return ZERO
30524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        assert dt.tzinfo is self
30534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Find first Sunday in April.
30554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
30564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        assert start.weekday() == 6 and start.month == 4 and start.day <= 7
30574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Find last Sunday in October.
30594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))
30604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        assert end.weekday() == 6 and end.month == 10 and end.day >= 25
30614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Can't compare naive to aware objects, so strip the timezone from
30634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # dt first.
30644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if start <= dt.replace(tzinfo=None) < end:
30654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return HOUR
30664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
30674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return ZERO
30684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmEastern  = USTimeZone(-5, "Eastern",  "EST", "EDT")
30704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmCentral  = USTimeZone(-6, "Central",  "CST", "CDT")
30714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMountain = USTimeZone(-7, "Mountain", "MST", "MDT")
30724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPacific  = USTimeZone(-8, "Pacific",  "PST", "PDT")
30734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmutc_real = FixedOffset(0, "UTC", 0)
30744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# For better test coverage, we want another flavor of UTC that's west of
30754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# the Eastern and Pacific timezones.
30764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmutc_fake = FixedOffset(-12*60, "UTCfake", 0)
30774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestTimezoneConversions(unittest.TestCase):
30794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # The DST switch times for 2002, in std time.
30804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    dston = datetime(2002, 4, 7, 2)
30814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    dstoff = datetime(2002, 10, 27, 1)
30824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    theclass = datetime
30844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Check a time that's inside DST.
30864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def checkinside(self, dt, tz, utc, dston, dstoff):
30874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.dst(), HOUR)
30884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Conversion to our own timezone is always an identity.
30904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.astimezone(tz), dt)
30914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        asutc = dt.astimezone(utc)
30934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        there_and_back = asutc.astimezone(tz)
30944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
30954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Conversion to UTC and back isn't always an identity here,
30964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # because there are redundant spellings (in local time) of
30974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # UTC time when DST begins:  the clock jumps from 1:59:59
30984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # to 3:00:00, and a local time of 2:MM:SS doesn't really
30994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # make sense then.  The classes above treat 2:MM:SS as
31004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # daylight time then (it's "after 2am"), really an alias
31014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # for 1:MM:SS standard time.  The latter form is what
31024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # conversion back from UTC produces.
31034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if dt.date() == dston.date() and dt.hour == 2:
31044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # We're in the redundant hour, and coming back from
31054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # UTC gives the 1:MM:SS standard-time spelling.
31064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(there_and_back + HOUR, dt)
31074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Although during was considered to be in daylight
31084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # time, there_and_back is not.
31094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(there_and_back.dst(), ZERO)
31104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # They're the same times in UTC.
31114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(there_and_back.astimezone(utc),
31124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             dt.astimezone(utc))
31134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
31144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # We're not in the redundant hour.
31154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(dt, there_and_back)
31164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
31174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Because we have a redundant spelling when DST begins, there is
31184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # (unfortunately) an hour when DST ends that can't be spelled at all in
31194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # local time.  When DST ends, the clock jumps from 1:59 back to 1:00
31204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # again.  The hour 1:MM DST has no spelling then:  1:MM is taken to be
31214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # standard time.  1:MM DST == 0:MM EST, but 0:MM is taken to be
31224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # daylight time.  The hour 1:MM daylight == 0:MM standard can't be
31234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # expressed in local time.  Nevertheless, we want conversion back
31244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # from UTC to mimic the local clock's "repeat an hour" behavior.
31254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        nexthour_utc = asutc + HOUR
31264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        nexthour_tz = nexthour_utc.astimezone(tz)
31274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if dt.date() == dstoff.date() and dt.hour == 0:
31284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # We're in the hour before the last DST hour.  The last DST hour
31294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # is ineffable.  We want the conversion back to repeat 1:MM.
31304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(nexthour_tz, dt.replace(hour=1))
31314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            nexthour_utc += HOUR
31324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            nexthour_tz = nexthour_utc.astimezone(tz)
31334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(nexthour_tz, dt.replace(hour=1))
31344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
31354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(nexthour_tz - dt, HOUR)
31364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
31374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Check a time that's outside DST.
31384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def checkoutside(self, dt, tz, utc):
31394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.dst(), ZERO)
31404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
31414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Conversion to our own timezone is always an identity.
31424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt.astimezone(tz), dt)
31434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
31444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Converting to UTC and back is an identity too.
31454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        asutc = dt.astimezone(utc)
31464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        there_and_back = asutc.astimezone(tz)
31474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(dt, there_and_back)
31484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
31494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def convert_between_tz_and_utc(self, tz, utc):
31504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dston = self.dston.replace(tzinfo=tz)
31514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Because 1:MM on the day DST ends is taken as being standard time,
31524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # there is no spelling in tz for the last hour of daylight time.
31534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # For purposes of the test, the last hour of DST is 0:MM, which is
31544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # taken as being daylight time (and 1:MM is taken as being standard
31554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # time).
31564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dstoff = self.dstoff.replace(tzinfo=tz)
31574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for delta in (timedelta(weeks=13),
31584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      DAY,
31594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      HOUR,
31604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      timedelta(minutes=1),
31614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      timedelta(microseconds=1)):
31624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
31634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.checkinside(dston, tz, utc, dston, dstoff)
31644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for during in dston + delta, dstoff - delta:
31654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.checkinside(during, tz, utc, dston, dstoff)
31664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
31674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.checkoutside(dstoff, tz, utc)
31684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for outside in dston - delta, dstoff + delta:
31694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.checkoutside(outside, tz, utc)
31704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
31714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_easy(self):
31724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Despite the name of this test, the endcases are excruciating.
31734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.convert_between_tz_and_utc(Eastern, utc_real)
31744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.convert_between_tz_and_utc(Pacific, utc_real)
31754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.convert_between_tz_and_utc(Eastern, utc_fake)
31764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.convert_between_tz_and_utc(Pacific, utc_fake)
31774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # The next is really dancing near the edge.  It works because
31784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Pacific and Eastern are far enough apart that their "problem
31794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # hours" don't overlap.
31804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.convert_between_tz_and_utc(Eastern, Pacific)
31814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.convert_between_tz_and_utc(Pacific, Eastern)
31824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # OTOH, these fail!  Don't enable them.  The difficulty is that
31834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # the edge case tests assume that every hour is representable in
31844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # the "utc" class.  This is always true for a fixed-offset tzinfo
31854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # class (lke utc_real and utc_fake), but not for Eastern or Central.
31864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # For these adjacent DST-aware time zones, the range of time offsets
31874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # tested ends up creating hours in the one that aren't representable
31884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # in the other.  For the same reason, we would see failures in the
31894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Eastern vs Pacific tests too if we added 3*HOUR to the list of
31904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # offset deltas in convert_between_tz_and_utc().
31914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #
31924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # self.convert_between_tz_and_utc(Eastern, Central)  # can't work
31934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # self.convert_between_tz_and_utc(Central, Eastern)  # can't work
31944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
31954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_tricky(self):
31964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # 22:00 on day before daylight starts.
31974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        fourback = self.dston - timedelta(hours=4)
31984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ninewest = FixedOffset(-9*60, "-0900", 0)
31994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        fourback = fourback.replace(tzinfo=ninewest)
32004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # 22:00-0900 is 7:00 UTC == 2:00 EST == 3:00 DST.  Since it's "after
32014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # 2", we should get the 3 spelling.
32024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # If we plug 22:00 the day before into Eastern, it "looks like std
32034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # time", so its offset is returned as -5, and -5 - -9 = 4.  Adding 4
32044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # to 22:00 lands on 2:00, which makes no sense in local time (the
32054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # local clock jumps from 1 to 3).  The point here is to make sure we
32064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # get the 3 spelling.
32074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = self.dston.replace(hour=3)
32084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        got = fourback.astimezone(Eastern).replace(tzinfo=None)
32094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(expected, got)
32104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Similar, but map to 6:00 UTC == 1:00 EST == 2:00 DST.  In that
32124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # case we want the 1:00 spelling.
32134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        sixutc = self.dston.replace(hour=6, tzinfo=utc_real)
32144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Now 6:00 "looks like daylight", so the offset wrt Eastern is -4,
32154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # and adding -4-0 == -4 gives the 2:00 spelling.  We want the 1:00 EST
32164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # spelling.
32174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        expected = self.dston.replace(hour=1)
32184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        got = sixutc.astimezone(Eastern).replace(tzinfo=None)
32194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(expected, got)
32204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Now on the day DST ends, we want "repeat an hour" behavior.
32224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  UTC  4:MM  5:MM  6:MM  7:MM  checking these
32234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  EST 23:MM  0:MM  1:MM  2:MM
32244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  EDT  0:MM  1:MM  2:MM  3:MM
32254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # wall  0:MM  1:MM  1:MM  2:MM  against these
32264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for utc in utc_real, utc_fake:
32274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for tz in Eastern, Pacific:
32284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                first_std_hour = self.dstoff - timedelta(hours=2) # 23:MM
32294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Convert that to UTC.
32304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                first_std_hour -= tz.utcoffset(None)
32314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Adjust for possibly fake UTC.
32324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                asutc = first_std_hour + utc.utcoffset(None)
32334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # First UTC hour to convert; this is 4:00 when utc=utc_real &
32344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # tz=Eastern.
32354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                asutcbase = asutc.replace(tzinfo=utc)
32364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                for tzhour in (0, 1, 1, 2):
32374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    expectedbase = self.dstoff.replace(hour=tzhour)
32384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    for minute in 0, 30, 59:
32394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        expected = expectedbase.replace(minute=minute)
32404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        asutc = asutcbase.replace(minute=minute)
32414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        astz = asutc.astimezone(tz)
32424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        self.assertEqual(astz.replace(tzinfo=None), expected)
32434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    asutcbase += HOUR
32444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bogus_dst(self):
32474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class ok(tzinfo):
32484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def utcoffset(self, dt): return HOUR
32494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt): return HOUR
32504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        now = self.theclass.now().replace(tzinfo=utc_real)
32524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Doesn't blow up.
32534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        now.astimezone(ok())
32544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Does blow up.
32564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class notok(ok):
32574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def dst(self, dt): return None
32584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, now.astimezone, notok())
32594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_fromutc(self):
32614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, Eastern.fromutc)   # not enough args
32624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        now = datetime.utcnow().replace(tzinfo=utc_real)
32634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(ValueError, Eastern.fromutc, now) # wrong tzinfo
32644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        now = now.replace(tzinfo=Eastern)   # insert correct tzinfo
32654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        enow = Eastern.fromutc(now)         # doesn't blow up
32664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(enow.tzinfo, Eastern) # has right tzinfo member
32674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, Eastern.fromutc, now, now) # too many args
32684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, Eastern.fromutc, date.today()) # wrong type
32694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Always converts UTC to standard time.
32714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class FauxUSTimeZone(USTimeZone):
32724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def fromutc(self, dt):
32734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return dt + self.stdoffset
32744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        FEastern  = FauxUSTimeZone(-5, "FEastern",  "FEST", "FEDT")
32754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  UTC  4:MM  5:MM  6:MM  7:MM  8:MM  9:MM
32774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  EST 23:MM  0:MM  1:MM  2:MM  3:MM  4:MM
32784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #  EDT  0:MM  1:MM  2:MM  3:MM  4:MM  5:MM
32794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Check around DST start.
32814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        start = self.dston.replace(hour=4, tzinfo=Eastern)
32824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        fstart = start.replace(tzinfo=FEastern)
32834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for wall in 23, 0, 1, 3, 4, 5:
32844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            expected = start.replace(hour=wall)
32854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if wall == 23:
32864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                expected -= timedelta(days=1)
32874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = Eastern.fromutc(start)
32884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
32894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            expected = fstart + FEastern.stdoffset
32914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = FEastern.fromutc(fstart)
32924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
32934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Ensure astimezone() calls fromutc() too.
32954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = fstart.replace(tzinfo=utc_real).astimezone(FEastern)
32964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
32974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
32984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            start += HOUR
32994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            fstart += HOUR
33004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Check around DST end.
33024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        start = self.dstoff.replace(hour=4, tzinfo=Eastern)
33034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        fstart = start.replace(tzinfo=FEastern)
33044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for wall in 0, 1, 1, 2, 3, 4:
33054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            expected = start.replace(hour=wall)
33064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = Eastern.fromutc(start)
33074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
33084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            expected = fstart + FEastern.stdoffset
33104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = FEastern.fromutc(fstart)
33114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
33124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Ensure astimezone() calls fromutc() too.
33144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            got = fstart.replace(tzinfo=utc_real).astimezone(FEastern)
33154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(expected, got)
33164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            start += HOUR
33184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            fstart += HOUR
33194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#############################################################################
33224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# oddballs
33234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass Oddballs(unittest.TestCase):
33254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bug_1028306(self):
33274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Trying to compare a date to a datetime should act like a mixed-
33284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # type comparison, despite that datetime is a subclass of date.
33294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        as_date = date.today()
33304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        as_datetime = datetime.combine(as_date, time())
33314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(as_date != as_datetime)
33324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(as_datetime != as_date)
33334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not as_date == as_datetime)
33344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not as_datetime == as_date)
33354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: as_date < as_datetime)
33364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: as_datetime < as_date)
33374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: as_date <= as_datetime)
33384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: as_datetime <= as_date)
33394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: as_date > as_datetime)
33404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: as_datetime > as_date)
33414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: as_date >= as_datetime)
33424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, lambda: as_datetime >= as_date)
33434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Neverthelss, comparison should work with the base-class (date)
33454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # projection if use of a date method is forced.
33464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(as_date.__eq__(as_datetime))
33474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        different_day = (as_date.day + 1) % 20 + 1
33484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not as_date.__eq__(as_datetime.replace(day=
33494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                                     different_day)))
33504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # And date should compare with other subclasses of date.  If a
33524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # subclass wants to stop this, it's up to the subclass to do so.
33534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        date_sc = SubclassDate(as_date.year, as_date.month, as_date.day)
33544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(as_date, date_sc)
33554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(date_sc, as_date)
33564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ditto for datetimes.
33584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        datetime_sc = SubclassDatetime(as_datetime.year, as_datetime.month,
33594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                       as_date.day, 0, 0, 0)
33604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(as_datetime, datetime_sc)
33614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(datetime_sc, as_datetime)
33624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test_main():
33644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test_support.run_unittest(__name__)
33654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
33664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == "__main__":
33674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test_main()
3368