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