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