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