1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""Test date/time type. 2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehSee http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases 4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh""" 5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom __future__ import division 6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys 7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport pickle 8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport cPickle 9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport unittest 10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom test import test_support 12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom datetime import MINYEAR, MAXYEAR 14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom datetime import timedelta 15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom datetime import tzinfo 16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom datetime import time 17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom datetime import date, datetime 18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehpickle_choices = [(pickler, unpickler, proto) 20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler in pickle, cPickle 21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for unpickler in pickle, cPickle 22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for proto in range(3)] 23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehassert len(pickle_choices) == 2*2*3 24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# An arbitrary collection of objects of non-datetime types, for testing 26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# mixed-type comparisons. 27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehOTHERSTUFF = (10, 10L, 34.5, "abc", {}, [], ()) 28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh############################################################################# 31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# module tests 32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestModule(unittest.TestCase): 34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_constants(self): 36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import datetime 37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(datetime.MINYEAR, 1) 38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(datetime.MAXYEAR, 9999) 39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh############################################################################# 41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# tzinfo tests 42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass FixedOffset(tzinfo): 44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, offset, name, dstoffset=42): 45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(offset, int): 46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh offset = timedelta(minutes=offset) 47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(dstoffset, int): 48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dstoffset = timedelta(minutes=dstoffset) 49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__offset = offset 50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__name = name 51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__dstoffset = dstoffset 52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __repr__(self): 53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.__name.lower() 54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): 55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.__offset 56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tzname(self, dt): 57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.__name 58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): 59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.__dstoffset 60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass PicklableFixedOffset(FixedOffset): 62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, offset=None, name=None, dstoffset=None): 63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh FixedOffset.__init__(self, offset, name, dstoffset) 64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestTZInfo(unittest.TestCase): 66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_non_abstractness(self): 68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # In order to allow subclasses to get pickled, the C implementation 69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # wasn't able to get away with having __init__ raise 70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # NotImplementedError. 71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh useless = tzinfo() 72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = datetime.max 73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(NotImplementedError, useless.tzname, dt) 74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(NotImplementedError, useless.utcoffset, dt) 75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(NotImplementedError, useless.dst, dt) 76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_subclass_must_override(self): 78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class NotEnough(tzinfo): 79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, offset, name): 80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__offset = offset 81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__name = name 82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(issubclass(NotEnough, tzinfo)) 83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ne = NotEnough(3, "NotByALongShot") 84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(ne, tzinfo) 85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = datetime.now() 87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(NotImplementedError, ne.tzname, dt) 88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(NotImplementedError, ne.utcoffset, dt) 89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(NotImplementedError, ne.dst, dt) 90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_normal(self): 92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fo = FixedOffset(3, "Three") 93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(fo, tzinfo) 94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dt in datetime.now(), None: 95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(fo.utcoffset(dt), timedelta(minutes=3)) 96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(fo.tzname(dt), "Three") 97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(fo.dst(dt), timedelta(minutes=42)) 98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling_base(self): 100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # There's no point to pickling tzinfo objects on their own (they 101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # carry no data), but they need to be picklable anyway else 102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # concrete subclasses can't be pickled. 103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = tzinfo.__new__(tzinfo) 104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(type(orig) is tzinfo) 105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(type(derived) is tzinfo) 109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling_subclass(self): 111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make sure we can pickle/unpickle an instance of a subclass. 112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh offset = timedelta(minutes=-300) 113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = PicklableFixedOffset(offset, 'cookie') 114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(orig, tzinfo) 115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(type(orig) is PicklableFixedOffset) 116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig.utcoffset(None), offset) 117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig.tzname(None), 'cookie') 118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(derived, tzinfo) 122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(type(derived) is PicklableFixedOffset) 123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(derived.utcoffset(None), offset) 124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(derived.tzname(None), 'cookie') 125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh############################################################################# 127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Base clase for testing a particular aspect of timedelta, time, date and 128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# datetime comparisons. 129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass HarmlessMixedComparison: 131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Test that __eq__ and __ne__ don't complain for mixed-type comparisons. 132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Subclasses must define 'theclass', and theclass(1, 1, 1) must be a 134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # legit constructor. 135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_harmless_mixed_comparison(self): 137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh me = self.theclass(1, 1, 1) 138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertFalse(me == ()) 140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(me != ()) 141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertFalse(() == me) 142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(() != me) 143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIn(me, [1, 20L, [], me]) 145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIn([], [me, 1, 20L, []]) 146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_harmful_mixed_comparison(self): 148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh me = self.theclass(1, 1, 1) 149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: me < ()) 151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: me <= ()) 152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: me > ()) 153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: me >= ()) 154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: () < me) 156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: () <= me) 157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: () > me) 158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: () >= me) 159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, cmp, (), me) 161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, cmp, me, ()) 162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh############################################################################# 164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# timedelta tests 165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestTimeDelta(HarmlessMixedComparison, unittest.TestCase): 167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theclass = timedelta 169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_constructor(self): 171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq = self.assertEqual 172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta 173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check keyword args to constructor 175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(), td(weeks=0, days=0, hours=0, minutes=0, seconds=0, 176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh milliseconds=0, microseconds=0)) 177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(1), td(days=1)) 178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(0, 1), td(seconds=1)) 179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(0, 0, 1), td(microseconds=1)) 180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(weeks=1), td(days=7)) 181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(days=1), td(hours=24)) 182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(hours=1), td(minutes=60)) 183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(minutes=1), td(seconds=60)) 184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(seconds=1), td(milliseconds=1000)) 185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(milliseconds=1), td(microseconds=1000)) 186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check float args to constructor 188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(weeks=1.0/7), td(days=1)) 189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(days=1.0/24), td(hours=1)) 190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(hours=1.0/60), td(minutes=1)) 191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(minutes=1.0/60), td(seconds=1)) 192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(seconds=0.001), td(milliseconds=1)) 193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(milliseconds=0.001), td(microseconds=1)) 194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_computations(self): 196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq = self.assertEqual 197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta 198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = td(7) # One week 200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = td(0, 60) # One minute 201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh c = td(0, 0, 1000) # One millisecond 202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(a+b+c, td(7, 60, 1000)) 203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(a-b, td(6, 24*3600 - 60)) 204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(-a, td(-7)) 205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(+a, td(7)) 206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(-b, td(-1, 24*3600 - 60)) 207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(-c, td(-1, 24*3600 - 1, 999000)) 208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(abs(a), a) 209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(abs(-a), a) 210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(6, 24*3600), a) 211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(0, 0, 60*1000000), b) 212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(a*10, td(70)) 213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(a*10, 10*a) 214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(a*10L, 10*a) 215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(b*10, td(0, 600)) 216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(10*b, td(0, 600)) 217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(b*10L, td(0, 600)) 218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(c*10, td(0, 0, 10000)) 219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(10*c, td(0, 0, 10000)) 220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(c*10L, td(0, 0, 10000)) 221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(a*-1, -a) 222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(b*-2, -b-b) 223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(c*-2, -c+-c) 224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(b*(60*24), (b*60)*24) 225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(b*(60*24), (60*b)*24) 226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(c*1000, td(0, 1)) 227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(1000*c, td(0, 1)) 228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(a//7, td(1)) 229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(b//10, td(0, 6)) 230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(c//1000, td(0, 0, 1)) 231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(a//10, td(0, 7*24*360)) 232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(a//3600000, td(0, 0, 7*24*1000)) 233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Issue #11576 235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(999999999, 86399, 999999) - td(999999999, 86399, 999998), 236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td(0, 0, 1)) 237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(999999999, 1, 1) - td(999999999, 1, 0), 238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td(0, 0, 1)) 239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_disallowed_computations(self): 242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = timedelta(42) 243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Add/sub ints, longs, floats should be illegal 245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in 1, 1L, 1.0: 246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a+i) 247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a-i) 248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: i+a) 249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: i-a) 250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Mul/div by float isn't supported. 252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh x = 2.3 253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a*x) 254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: x*a) 255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a/x) 256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: x/a) 257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a // x) 258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: x // a) 259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Division of int by timedelta doesn't make sense. 261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Division by zero doesn't make sense. 262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for zero in 0, 0L: 263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: zero // a) 264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ZeroDivisionError, lambda: a // zero) 265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_basic_attributes(self): 267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh days, seconds, us = 1, 7, 31 268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta(days, seconds, us) 269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(td.days, days) 270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(td.seconds, seconds) 271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(td.microseconds, us) 272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_total_seconds(self): 274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta(days=365) 275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(td.total_seconds(), 31536000.0) 276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for total_seconds in [123456.789012, -123456.789012, 0.123456, 0, 1e6]: 277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta(seconds=total_seconds) 278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(td.total_seconds(), total_seconds) 279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Issue8644: Test that td.total_seconds() has the same 280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # accuracy as td / timedelta(seconds=1). 281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for ms in [-1, -2, -123]: 282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta(microseconds=ms) 283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(td.total_seconds(), 284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ((24*3600*td.days + td.seconds)*10**6 285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh + td.microseconds)/10**6) 286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_carries(self): 288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = timedelta(days=100, 289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh weeks=-7, 290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hours=-24*(100-49), 291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh minutes=-3, 292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh seconds=12, 293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh microseconds=(3*60 - 12) * 1e6 + 1) 294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = timedelta(microseconds=1) 295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_hash_equality(self): 298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = timedelta(days=100, 299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh weeks=-7, 300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hours=-24*(100-49), 301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh minutes=-3, 302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh seconds=12, 303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh microseconds=(3*60 - 12) * 1000000) 304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = timedelta() 305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(t1), hash(t2)) 306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 += timedelta(weeks=7) 308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 += timedelta(days=7*7) 309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(t1), hash(t2)) 311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = {t1: 1} 313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d[t2] = 2 314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(len(d), 1) 315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d[t1], 2) 316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling(self): 318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 12, 34, 56 319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = timedelta(*args) 320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_compare(self): 326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = timedelta(2, 3, 4) 327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = timedelta(2, 3, 4) 328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 == t2) 329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 <= t2) 330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 >= t2) 331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 != t2) 332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 < t2) 333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 > t2) 334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t1, t2), 0) 335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t2, t1), 0) 336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for args in (3, 3, 3), (2, 4, 4), (2, 3, 5): 338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = timedelta(*args) # this is larger than t1 339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 < t2) 340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 > t1) 341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 <= t2) 342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 >= t1) 343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 != t2) 344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 != t1) 345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 == t2) 346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 == t1) 347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 > t2) 348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 < t1) 349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 >= t2) 350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 <= t1) 351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t1, t2), -1) 352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t2, t1), 1) 353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for badarg in OTHERSTUFF: 355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1 == badarg, False) 356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1 != badarg, True) 357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(badarg == t1, False) 358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(badarg != t1, True) 359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 <= badarg) 361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 < badarg) 362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 > badarg) 363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 >= badarg) 364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg <= t1) 365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg < t1) 366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg > t1) 367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg >= t1) 368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_str(self): 370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta 371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq = self.assertEqual 372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(str(td(1)), "1 day, 0:00:00") 374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(str(td(-1)), "-1 day, 0:00:00") 375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(str(td(2)), "2 days, 0:00:00") 376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(str(td(-2)), "-2 days, 0:00:00") 377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(str(td(hours=12, minutes=58, seconds=59)), "12:58:59") 379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(str(td(hours=2, minutes=3, seconds=4)), "2:03:04") 380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(str(td(weeks=-30, hours=23, minutes=12, seconds=34)), 381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "-210 days, 23:12:34") 382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(str(td(milliseconds=1)), "0:00:00.001000") 384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(str(td(microseconds=3)), "0:00:00.000003") 385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(str(td(days=999999999, hours=23, minutes=59, seconds=59, 387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh microseconds=999999)), 388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "999999999 days, 23:59:59.999999") 389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_roundtrip(self): 391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for td in (timedelta(days=999999999, hours=23, minutes=59, 392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh seconds=59, microseconds=999999), 393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timedelta(days=-999999999), 394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timedelta(days=1, seconds=2, microseconds=3)): 395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Verify td -> string -> td identity. 397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = repr(td) 398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(s.startswith('datetime.')) 399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = s[9:] 400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td2 = eval(s) 401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(td, td2) 402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Verify identity via reconstructing from pieces. 404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td2 = timedelta(td.days, td.seconds, td.microseconds) 405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(td, td2) 406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_resolution_info(self): 408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(timedelta.min, timedelta) 409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(timedelta.max, timedelta) 410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(timedelta.resolution, timedelta) 411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(timedelta.max > timedelta.min) 412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(timedelta.min, timedelta(-999999999)) 413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(timedelta.max, timedelta(999999999, 24*3600-1, 1e6-1)) 414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(timedelta.resolution, timedelta(0, 0, 1)) 415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_overflow(self): 417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tiny = timedelta.resolution 418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta.min + tiny 420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td -= tiny # no problem 421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, td.__sub__, tiny) 422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, td.__add__, -tiny) 423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta.max - tiny 425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td += tiny # no problem 426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, td.__add__, tiny) 427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, td.__sub__, -tiny) 428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, lambda: -timedelta.max) 430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_microsecond_rounding(self): 432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta 433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq = self.assertEqual 434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Single-field rounding. 436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(milliseconds=0.4/1000), td(0)) # rounds to 0 437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(milliseconds=-0.4/1000), td(0)) # rounds to 0 438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(milliseconds=0.6/1000), td(microseconds=1)) 439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(milliseconds=-0.6/1000), td(microseconds=-1)) 440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Rounding due to contributions from more than one field. 442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh us_per_hour = 3600e6 443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh us_per_day = us_per_hour * 24 444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(days=.4/us_per_day), td(0)) 445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(hours=.2/us_per_hour), td(0)) 446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(days=.4/us_per_day, hours=.2/us_per_hour), td(microseconds=1)) 447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(days=-.4/us_per_day), td(0)) 449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(hours=-.2/us_per_hour), td(0)) 450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eq(td(days=-.4/us_per_day, hours=-.2/us_per_hour), td(microseconds=-1)) 451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_massive_normalization(self): 453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh td = timedelta(microseconds=-1) 454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((td.days, td.seconds, td.microseconds), 455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (-1, 24*3600-1, 999999)) 456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bool(self): 458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(timedelta(1)) 459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(timedelta(0, 1)) 460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(timedelta(0, 0, 1)) 461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(timedelta(microseconds=1)) 462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not timedelta(0)) 463ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 464ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_subclass_timedelta(self): 465ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 466ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class T(timedelta): 467ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh @staticmethod 468ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def from_td(td): 469ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return T(td.days, td.seconds, td.microseconds) 470ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 471ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def as_hours(self): 472ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sum = (self.days * 24 + 473ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.seconds / 3600.0 + 474ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.microseconds / 3600e6) 475ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return round(sum) 476ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 477ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = T(days=1) 478ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(type(t1) is T) 479ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.as_hours(), 24) 480ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 481ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = T(days=-1, seconds=-3600) 482ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(type(t2) is T) 483ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.as_hours(), -25) 484ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 485ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t3 = t1 + t2 486ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(type(t3) is timedelta) 487ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t4 = T.from_td(t3) 488ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(type(t4) is T) 489ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.days, t4.days) 490ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.seconds, t4.seconds) 491ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.microseconds, t4.microseconds) 492ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t3), str(t4)) 493ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t4.as_hours(), -1) 494ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 495ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh############################################################################# 496ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# date tests 497ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 498ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestDateOnly(unittest.TestCase): 499ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Tests here won't pass if also run on datetime objects, so don't 500ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # subclass this to test datetimes too. 501ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 502ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_delta_non_days_ignored(self): 503ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = date(2000, 1, 2) 504ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh delta = timedelta(days=1, hours=2, minutes=3, seconds=4, 505ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh microseconds=5) 506ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh days = timedelta(delta.days) 507ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(days, timedelta(1)) 508ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 509ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = dt + delta 510ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2, dt + days) 511ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 512ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = delta + dt 513ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2, dt + days) 514ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 515ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = dt - delta 516ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2, dt - days) 517ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 518ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh delta = -delta 519ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh days = timedelta(delta.days) 520ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(days, timedelta(-2)) 521ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 522ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = dt + delta 523ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2, dt + days) 524ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 525ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = delta + dt 526ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2, dt + days) 527ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 528ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = dt - delta 529ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2, dt - days) 530ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 531ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass SubclassDate(date): 532ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sub_var = 1 533ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 534ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestDate(HarmlessMixedComparison, unittest.TestCase): 535ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Tests here should pass for both dates and datetimes, except for a 536ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # few tests that TestDateTime overrides. 537ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 538ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theclass = date 539ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 540ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_basic_attributes(self): 541ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass(2002, 3, 1) 542ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.year, 2002) 543ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.month, 3) 544ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.day, 1) 545ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 546ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_roundtrip(self): 547ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dt in (self.theclass(1, 2, 3), 548ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass.today()): 549ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Verify dt -> string -> date identity. 550ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = repr(dt) 551ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(s.startswith('datetime.')) 552ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = s[9:] 553ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = eval(s) 554ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt, dt2) 555ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 556ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Verify identity via reconstructing from pieces. 557ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = self.theclass(dt.year, dt.month, dt.day) 558ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt, dt2) 559ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 560ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_ordinal_conversions(self): 561ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check some fixed values. 562ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for y, m, d, n in [(1, 1, 1, 1), # calendar origin 563ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (1, 12, 31, 365), 564ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (2, 1, 1, 366), 565ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # first example from "Calendrical Calculations" 566ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (1945, 11, 12, 710347)]: 567ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(y, m, d) 568ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(n, d.toordinal()) 569ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fromord = self.theclass.fromordinal(n) 570ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, fromord) 571ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if hasattr(fromord, "hour"): 572ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # if we're checking something fancier than a date, verify 573ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the extra fields have been zeroed out 574ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(fromord.hour, 0) 575ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(fromord.minute, 0) 576ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(fromord.second, 0) 577ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(fromord.microsecond, 0) 578ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 579ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check first and last days of year spottily across the whole 580ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # range of years supported. 581ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for year in xrange(MINYEAR, MAXYEAR+1, 7): 582ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Verify (year, 1, 1) -> ordinal -> y, m, d is identity. 583ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(year, 1, 1) 584ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh n = d.toordinal() 585ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d2 = self.theclass.fromordinal(n) 586ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, d2) 587ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Verify that moving back a day gets to the end of year-1. 588ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if year > 1: 589ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass.fromordinal(n-1) 590ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d2 = self.theclass(year-1, 12, 31) 591ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, d2) 592ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d2.toordinal(), n-1) 593ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 594ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Test every day in a leap-year and a non-leap year. 595ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dim = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] 596ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for year, isleap in (2000, True), (2002, False): 597ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh n = self.theclass(year, 1, 1).toordinal() 598ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for month, maxday in zip(range(1, 13), dim): 599ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if month == 2 and isleap: 600ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh maxday += 1 601ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for day in range(1, maxday+1): 602ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(year, month, day) 603ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.toordinal(), n) 604ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, self.theclass.fromordinal(n)) 605ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh n += 1 606ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 607ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_extreme_ordinals(self): 608ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = self.theclass.min 609ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = self.theclass(a.year, a.month, a.day) # get rid of time parts 610ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh aord = a.toordinal() 611ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = a.fromordinal(aord) 612ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a, b) 613ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 614ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, lambda: a.fromordinal(aord - 1)) 615ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 616ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = a + timedelta(days=1) 617ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.toordinal(), aord + 1) 618ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b, self.theclass.fromordinal(aord + 1)) 619ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 620ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = self.theclass.max 621ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = self.theclass(a.year, a.month, a.day) # get rid of time parts 622ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh aord = a.toordinal() 623ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = a.fromordinal(aord) 624ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a, b) 625ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 626ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, lambda: a.fromordinal(aord + 1)) 627ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 628ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = a - timedelta(days=1) 629ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.toordinal(), aord - 1) 630ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b, self.theclass.fromordinal(aord - 1)) 631ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 632ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bad_constructor_arguments(self): 633ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad years 634ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(MINYEAR, 1, 1) # no exception 635ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(MAXYEAR, 1, 1) # no exception 636ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1) 637ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1) 638ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad months 639ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 1, 1) # no exception 640ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 12, 1) # no exception 641ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 0, 1) 642ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 13, 1) 643ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad days 644ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 2, 29) # no exception 645ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2004, 2, 29) # no exception 646ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2400, 2, 29) # no exception 647ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 2, 30) 648ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2001, 2, 29) 649ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2100, 2, 29) 650ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 1900, 2, 29) 651ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 1, 0) 652ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 1, 32) 653ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 654ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_hash_equality(self): 655ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2000, 12, 31) 656ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # same thing 657ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh e = self.theclass(2000, 12, 31) 658ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, e) 659ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(d), hash(e)) 660ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 661ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic = {d: 1} 662ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic[e] = 2 663ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(len(dic), 1) 664ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[d], 2) 665ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[e], 2) 666ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 667ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2001, 1, 1) 668ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # same thing 669ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh e = self.theclass(2001, 1, 1) 670ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, e) 671ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(d), hash(e)) 672ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 673ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic = {d: 1} 674ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic[e] = 2 675ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(len(dic), 1) 676ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[d], 2) 677ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[e], 2) 678ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 679ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_computations(self): 680ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = self.theclass(2002, 1, 31) 681ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = self.theclass(1956, 1, 31) 682ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 683ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh diff = a-b 684ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4))) 685ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(diff.seconds, 0) 686ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(diff.microseconds, 0) 687ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 688ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh day = timedelta(1) 689ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh week = timedelta(7) 690ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = self.theclass(2002, 3, 2) 691ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a + day, self.theclass(2002, 3, 3)) 692ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(day + a, self.theclass(2002, 3, 3)) 693ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - day, self.theclass(2002, 3, 1)) 694ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(-day + a, self.theclass(2002, 3, 1)) 695ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a + week, self.theclass(2002, 3, 9)) 696ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - week, self.theclass(2002, 2, 23)) 697ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a + 52*week, self.theclass(2003, 3, 1)) 698ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - 52*week, self.theclass(2001, 3, 3)) 699ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a + week) - a, week) 700ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a + day) - a, day) 701ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a - week) - a, -week) 702ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a - day) - a, -day) 703ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a + week), -week) 704ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a + day), -day) 705ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a - week), week) 706ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a - day), day) 707ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 708ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Add/sub ints, longs, floats should be illegal 709ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in 1, 1L, 1.0: 710ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a+i) 711ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a-i) 712ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: i+a) 713ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: i-a) 714ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 715ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # delta - date is senseless. 716ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: day - a) 717ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # mixing date and (delta or date) via * or // is senseless 718ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: day * a) 719ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a * day) 720ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: day // a) 721ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a // day) 722ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a * a) 723ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a // a) 724ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # date + date is senseless 725ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a + a) 726ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 727ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_overflow(self): 728ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tiny = self.theclass.resolution 729ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 730ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for delta in [tiny, timedelta(1), timedelta(2)]: 731ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass.min + delta 732ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt -= delta # no problem 733ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, dt.__sub__, delta) 734ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, dt.__add__, -delta) 735ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 736ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass.max - delta 737ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt += delta # no problem 738ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, dt.__add__, delta) 739ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, dt.__sub__, -delta) 740ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 741ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_fromtimestamp(self): 742ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import time 743ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 744ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try an arbitrary fixed value. 745ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh year, month, day = 1999, 9, 19 746ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ts = time.mktime((year, month, day, 0, 0, 0, 0, 0, -1)) 747ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass.fromtimestamp(ts) 748ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.year, year) 749ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.month, month) 750ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.day, day) 751ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 752ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_insane_fromtimestamp(self): 753ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # It's possible that some platform maps time_t to double, 754ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # and that this test will fail there. This test should 755ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # exempt such platforms (provided they return reasonable 756ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # results!). 757ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for insane in -1e200, 1e200: 758ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass.fromtimestamp, 759ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh insane) 760ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 761ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_today(self): 762ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import time 763ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 764ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # We claim that today() is like fromtimestamp(time.time()), so 765ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # prove it. 766ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dummy in range(3): 767ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh today = self.theclass.today() 768ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ts = time.time() 769ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh todayagain = self.theclass.fromtimestamp(ts) 770ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if today == todayagain: 771ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 772ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # There are several legit reasons that could fail: 773ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 1. It recently became midnight, between the today() and the 774ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # time() calls. 775ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 2. The platform time() has such fine resolution that we'll 776ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # never get the same value twice. 777ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 3. The platform time() has poor resolution, and we just 778ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # happened to call today() right before a resolution quantum 779ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # boundary. 780ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 4. The system clock got fiddled between calls. 781ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # In any case, wait a little while and try again. 782ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time.sleep(0.1) 783ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 784ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # It worked or it didn't. If it didn't, assume it's reason #2, and 785ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # let the test pass if they're within half a second of each other. 786ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(today == todayagain or 787ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh abs(todayagain - today) < timedelta(seconds=0.5)) 788ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 789ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_weekday(self): 790ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in range(7): 791ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # March 4, 2002 is a Monday 792ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(self.theclass(2002, 3, 4+i).weekday(), i) 793ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(self.theclass(2002, 3, 4+i).isoweekday(), i+1) 794ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # January 2, 1956 is a Monday 795ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(self.theclass(1956, 1, 2+i).weekday(), i) 796ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(self.theclass(1956, 1, 2+i).isoweekday(), i+1) 797ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 798ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_isocalendar(self): 799ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check examples from 800ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm 801ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in range(7): 802ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2003, 12, 22+i) 803ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.isocalendar(), (2003, 52, i+1)) 804ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2003, 12, 29) + timedelta(i) 805ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.isocalendar(), (2004, 1, i+1)) 806ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2004, 1, 5+i) 807ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.isocalendar(), (2004, 2, i+1)) 808ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2009, 12, 21+i) 809ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.isocalendar(), (2009, 52, i+1)) 810ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2009, 12, 28) + timedelta(i) 811ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.isocalendar(), (2009, 53, i+1)) 812ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2010, 1, 4+i) 813ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.isocalendar(), (2010, 1, i+1)) 814ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 815ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_iso_long_years(self): 816ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Calculate long ISO years and compare to table from 817ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm 818ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ISO_LONG_YEARS_TABLE = """ 819ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 4 32 60 88 820ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 9 37 65 93 821ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 15 43 71 99 822ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 20 48 76 823ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 26 54 82 824ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 825ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 105 133 161 189 826ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 111 139 167 195 827ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 116 144 172 828ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 122 150 178 829ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 128 156 184 830ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 831ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 201 229 257 285 832ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 207 235 263 291 833ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 212 240 268 296 834ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 218 246 274 835ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 224 252 280 836ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 837ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 303 331 359 387 838ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 308 336 364 392 839ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 314 342 370 398 840ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 320 348 376 841ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 325 353 381 842ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 843ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh iso_long_years = map(int, ISO_LONG_YEARS_TABLE.split()) 844ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh iso_long_years.sort() 845ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh L = [] 846ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in range(400): 847ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2000+i, 12, 31) 848ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d1 = self.theclass(1600+i, 12, 31) 849ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.isocalendar()[1:], d1.isocalendar()[1:]) 850ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if d.isocalendar()[1] == 53: 851ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh L.append(i) 852ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(L, iso_long_years) 853ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 854ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_isoformat(self): 855ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(2, 3, 2) 856ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "0002-03-02") 857ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 858ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_ctime(self): 859ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(2002, 3, 2) 860ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.ctime(), "Sat Mar 2 00:00:00 2002") 861ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 862ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_strftime(self): 863ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(2005, 3, 2) 864ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.strftime("m:%m d:%d y:%y"), "m:03 d:02 y:05") 865ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.strftime(""), "") # SF bug #761337 866ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.strftime('x'*1000), 'x'*1000) # SF bug #1556784 867ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 868ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t.strftime) # needs an arg 869ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t.strftime, "one", "two") # too many args 870ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t.strftime, 42) # arg wrong type 871ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 872ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # test that unicode input is allowed (issue 2782) 873ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.strftime(u"%m"), "03") 874ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 875ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # A naive object replaces %z and %Z w/ empty strings. 876ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''") 877ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 878ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #make sure that invalid format specifiers are handled correctly 879ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #self.assertRaises(ValueError, t.strftime, "%e") 880ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #self.assertRaises(ValueError, t.strftime, "%") 881ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #self.assertRaises(ValueError, t.strftime, "%#") 882ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 883ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #oh well, some systems just ignore those invalid ones. 884ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #at least, excercise them to make sure that no crashes 885ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #are generated 886ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for f in ["%e", "%", "%#"]: 887ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 888ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.strftime(f) 889ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except ValueError: 890ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 891ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 892ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #check that this standard extension works 893ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.strftime("%f") 894ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 895ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 896ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_format(self): 897ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass(2007, 9, 10) 898ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.__format__(''), str(dt)) 899ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 900ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # check that a derived class's __str__() gets called 901ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class A(self.theclass): 902ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __str__(self): 903ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'A' 904ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = A(2007, 9, 10) 905ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a.__format__(''), 'A') 906ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 907ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # check that a derived class's strftime gets called 908ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class B(self.theclass): 909ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def strftime(self, format_spec): 910ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'B' 911ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = B(2007, 9, 10) 912ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.__format__(''), str(dt)) 913ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 914ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for fmt in ["m:%m d:%d y:%y", 915ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "m:%m d:%d y:%y H:%H M:%M S:%S", 916ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "%z %Z", 917ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ]: 918ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.__format__(fmt), dt.strftime(fmt)) 919ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a.__format__(fmt), dt.strftime(fmt)) 920ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.__format__(fmt), 'B') 921ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 922ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_resolution_info(self): 923ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(self.theclass.min, self.theclass) 924ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(self.theclass.max, self.theclass) 925ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(self.theclass.resolution, timedelta) 926ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(self.theclass.max > self.theclass.min) 927ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 928ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_extreme_timedelta(self): 929ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh big = self.theclass.max - self.theclass.min 930ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds 931ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds 932ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # n == 315537897599999999 ~= 2**58.13 933ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh justasbig = timedelta(0, 0, n) 934ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(big, justasbig) 935ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(self.theclass.min + big, self.theclass.max) 936ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(self.theclass.max - big, self.theclass.min) 937ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 938ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_timetuple(self): 939ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in range(7): 940ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # January 2, 1956 is a Monday (0) 941ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(1956, 1, 2+i) 942ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = d.timetuple() 943ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t, (1956, 1, 2+i, 0, 0, 0, i, 2+i, -1)) 944ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # February 1, 1956 is a Wednesday (2) 945ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(1956, 2, 1+i) 946ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = d.timetuple() 947ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t, (1956, 2, 1+i, 0, 0, 0, (2+i)%7, 32+i, -1)) 948ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # March 1, 1956 is a Thursday (3), and is the 31+29+1 = 61st day 949ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # of the year. 950ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(1956, 3, 1+i) 951ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = d.timetuple() 952ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t, (1956, 3, 1+i, 0, 0, 0, (3+i)%7, 61+i, -1)) 953ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_year, 1956) 954ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_mon, 3) 955ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_mday, 1+i) 956ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_hour, 0) 957ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_min, 0) 958ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_sec, 0) 959ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_wday, (3+i)%7) 960ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_yday, 61+i) 961ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_isdst, -1) 962ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 963ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling(self): 964ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 6, 7, 23 965ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = self.theclass(*args) 966ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 967ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 968ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 969ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 970ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 971ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_compare(self): 972ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(2, 3, 4) 973ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(2, 3, 4) 974ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 == t2) 975ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 <= t2) 976ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 >= t2) 977ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 != t2) 978ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 < t2) 979ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 > t2) 980ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t1, t2), 0) 981ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t2, t1), 0) 982ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 983ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for args in (3, 3, 3), (2, 4, 4), (2, 3, 5): 984ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(*args) # this is larger than t1 985ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 < t2) 986ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 > t1) 987ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 <= t2) 988ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 >= t1) 989ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 != t2) 990ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 != t1) 991ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 == t2) 992ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 == t1) 993ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 > t2) 994ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 < t1) 995ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 >= t2) 996ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 <= t1) 997ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t1, t2), -1) 998ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t2, t1), 1) 999ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1000ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for badarg in OTHERSTUFF: 1001ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1 == badarg, False) 1002ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1 != badarg, True) 1003ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(badarg == t1, False) 1004ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(badarg != t1, True) 1005ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1006ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 < badarg) 1007ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 > badarg) 1008ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 >= badarg) 1009ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg <= t1) 1010ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg < t1) 1011ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg > t1) 1012ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg >= t1) 1013ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1014ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_mixed_compare(self): 1015ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh our = self.theclass(2000, 4, 5) 1016ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, cmp, our, 1) 1017ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, cmp, 1, our) 1018ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1019ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class AnotherDateTimeClass(object): 1020ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __cmp__(self, other): 1021ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Return "equal" so calling this can't be confused with 1022ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # compare-by-address (which never says "equal" for distinct 1023ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # objects). 1024ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 0 1025ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh __hash__ = None # Silence Py3k warning 1026ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1027ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This still errors, because date and datetime comparison raise 1028ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # TypeError instead of NotImplemented when they don't know what to 1029ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # do, in order to stop comparison from falling back to the default 1030ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # compare-by-address. 1031ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh their = AnotherDateTimeClass() 1032ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, cmp, our, their) 1033ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Oops: The next stab raises TypeError in the C implementation, 1034ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # but not in the Python implementation of datetime. The difference 1035ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # is due to that the Python implementation defines __cmp__ but 1036ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the C implementation defines tp_richcompare. This is more pain 1037ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # to fix than it's worth, so commenting out the test. 1038ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # self.assertEqual(cmp(their, our), 0) 1039ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1040ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # But date and datetime comparison return NotImplemented instead if the 1041ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # other object has a timetuple attr. This gives the other object a 1042ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # chance to do the comparison. 1043ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class Comparable(AnotherDateTimeClass): 1044ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def timetuple(self): 1045ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return () 1046ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1047ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh their = Comparable() 1048ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(our, their), 0) 1049ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(their, our), 0) 1050ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(our == their) 1051ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(their == our) 1052ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1053ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bool(self): 1054ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # All dates are considered true. 1055ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(self.theclass.min) 1056ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(self.theclass.max) 1057ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1058ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_strftime_out_of_range(self): 1059ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # For nasty technical reasons, we can't handle years before 1900. 1060ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 1061ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cls(1900, 1, 1).strftime("%Y"), "1900") 1062ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for y in 1, 49, 51, 99, 100, 1000, 1899: 1063ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, cls(y, 1, 1).strftime, "%Y") 1064ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1065ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_replace(self): 1066ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 1067ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = [1, 2, 3] 1068ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(*args) 1069ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(base, base.replace()) 1070ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1071ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = 0 1072ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for name, newval in (("year", 2), 1073ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("month", 3), 1074ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("day", 4)): 1075ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs = args[:] 1076ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs[i] = newval 1077ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = cls(*newargs) 1078ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = base.replace(**{name: newval}) 1079ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 1080ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i += 1 1081ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1082ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Out of bounds. 1083ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(2000, 2, 29) 1084ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, year=2001) 1085ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1086ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_subclass_date(self): 1087ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1088ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class C(self.theclass): 1089ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theAnswer = 42 1090ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1091ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __new__(cls, *args, **kws): 1092ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh temp = kws.copy() 1093ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh extra = temp.pop('extra') 1094ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result = self.theclass.__new__(cls, *args, **temp) 1095ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result.extra = extra 1096ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return result 1097ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1098ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def newmeth(self, start): 1099ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return start + self.year + self.month 1100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 2003, 4, 14 1102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt1 = self.theclass(*args) 1104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = C(*args, **{'extra': 7}) 1105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.__class__, C) 1107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.theAnswer, 42) 1108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.extra, 7) 1109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt1.toordinal(), dt2.toordinal()) 1110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month - 7) 1111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling_subclass_date(self): 1113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 6, 7, 23 1115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = SubclassDate(*args) 1116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 1117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 1118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 1119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 1120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_backdoor_resistance(self): 1122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # For fast unpickling, the constructor accepts a pickle string. 1123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This is a low-overhead backdoor. A user can (by intent or 1124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # mistake) pass a string directly, which (if it's the right length) 1125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # will get treated like a pickle, and bypass the normal sanity 1126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # checks in the constructor. This can create insane objects. 1127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The constructor doesn't want to burn the time to validate all 1128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # fields, but does check the month field. This stops, e.g., 1129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # datetime.datetime('1995-03-25') from yielding an insane object. 1130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = '1995-03-25' 1131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not issubclass(self.theclass, datetime): 1132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = base[:4] 1133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for month_byte in '9', chr(0), chr(13), '\xff': 1134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, self.theclass, 1135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base[:2] + month_byte + base[3:]) 1136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for ord_byte in range(1, 13): 1137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This shouldn't blow up because of the month byte alone. If 1138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the implementation changes to do more-careful checking, it may 1139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # blow up because other fields are insane. 1140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(base[:2] + chr(ord_byte) + base[3:]) 1141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh############################################################################# 1143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# datetime tests 1144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass SubclassDatetime(datetime): 1146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sub_var = 1 1147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestDateTime(TestDate): 1149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theclass = datetime 1151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_basic_attributes(self): 1153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass(2002, 3, 1, 12, 0) 1154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.year, 2002) 1155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.month, 3) 1156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.day, 1) 1157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.hour, 12) 1158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.minute, 0) 1159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.second, 0) 1160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.microsecond, 0) 1161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_basic_attributes_nonzero(self): 1163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make sure all attributes are non-zero so bugs in 1164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bit-shifting access show up. 1165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass(2002, 3, 1, 12, 59, 59, 8000) 1166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.year, 2002) 1167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.month, 3) 1168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.day, 1) 1169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.hour, 12) 1170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.minute, 59) 1171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.second, 59) 1172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.microsecond, 8000) 1173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_roundtrip(self): 1175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7), 1176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass.now()): 1177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Verify dt -> string -> datetime identity. 1178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = repr(dt) 1179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(s.startswith('datetime.')) 1180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = s[9:] 1181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = eval(s) 1182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt, dt2) 1183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Verify identity via reconstructing from pieces. 1185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = self.theclass(dt.year, dt.month, dt.day, 1186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt.hour, dt.minute, dt.second, 1187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt.microsecond) 1188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt, dt2) 1189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_isoformat(self): 1191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(2, 3, 2, 4, 5, 1, 123) 1192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "0002-03-02T04:05:01.000123") 1193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat('T'), "0002-03-02T04:05:01.000123") 1194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123") 1195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat('\x00'), "0002-03-02\x0004:05:01.000123") 1196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # str is ISO format with the separator forced to a blank. 1197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t), "0002-03-02 04:05:01.000123") 1198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(2, 3, 2) 1200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "0002-03-02T00:00:00") 1201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat('T'), "0002-03-02T00:00:00") 1202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(' '), "0002-03-02 00:00:00") 1203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # str is ISO format with the separator forced to a blank. 1204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t), "0002-03-02 00:00:00") 1205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_format(self): 1207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass(2007, 9, 10, 4, 5, 1, 123) 1208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.__format__(''), str(dt)) 1209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # check that a derived class's __str__() gets called 1211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class A(self.theclass): 1212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __str__(self): 1213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'A' 1214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = A(2007, 9, 10, 4, 5, 1, 123) 1215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a.__format__(''), 'A') 1216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # check that a derived class's strftime gets called 1218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class B(self.theclass): 1219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def strftime(self, format_spec): 1220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'B' 1221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = B(2007, 9, 10, 4, 5, 1, 123) 1222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.__format__(''), str(dt)) 1223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for fmt in ["m:%m d:%d y:%y", 1225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "m:%m d:%d y:%y H:%H M:%M S:%S", 1226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "%z %Z", 1227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ]: 1228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.__format__(fmt), dt.strftime(fmt)) 1229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a.__format__(fmt), dt.strftime(fmt)) 1230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.__format__(fmt), 'B') 1231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_more_ctime(self): 1233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Test fields that TestDate doesn't touch. 1234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import time 1235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(2002, 3, 2, 18, 3, 5, 123) 1237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.ctime(), "Sat Mar 2 18:03:05 2002") 1238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Oops! The next line fails on Win2K under MSVC 6, so it's commented 1239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # out. The difference is that t.ctime() produces " 2" for the day, 1240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # but platform ctime() produces "02" for the day. According to 1241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # C99, t.ctime() is correct here. 1242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # self.assertEqual(t.ctime(), time.ctime(time.mktime(t.timetuple()))) 1243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # So test a case where that difference doesn't matter. 1245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(2002, 3, 22, 18, 3, 5, 123) 1246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.ctime(), time.ctime(time.mktime(t.timetuple()))) 1247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_tz_independent_comparing(self): 1249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt1 = self.theclass(2002, 3, 1, 9, 0, 0) 1250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = self.theclass(2002, 3, 1, 10, 0, 0) 1251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt3 = self.theclass(2002, 3, 1, 9, 0, 0) 1252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt1, dt3) 1253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(dt2 > dt3) 1254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make sure comparison doesn't forget microseconds, and isn't done 1256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # via comparing a float timestamp (an IEEE double doesn't have enough 1257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # precision to span microsecond resolution across years 1 thru 9999, 1258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # so comparing via timestamp necessarily calls some distinct values 1259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # equal). 1260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998) 1261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh us = timedelta(microseconds=1) 1262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = dt1 + us 1263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2 - dt1, us) 1264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(dt1 < dt2) 1265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_strftime_with_bad_tzname_replace(self): 1267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # verify ok if tzinfo.tzname().replace() returns a non-string 1268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class MyTzInfo(FixedOffset): 1269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tzname(self, dt): 1270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class MyStr(str): 1271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def replace(self, *args): 1272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None 1273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return MyStr('name') 1274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(2005, 3, 2, 0, 0, 0, 0, MyTzInfo(3, 'name')) 1275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t.strftime, '%Z') 1276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bad_constructor_arguments(self): 1278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad years 1279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(MINYEAR, 1, 1) # no exception 1280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(MAXYEAR, 1, 1) # no exception 1281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1) 1282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1) 1283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad months 1284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 1, 1) # no exception 1285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 12, 1) # no exception 1286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 0, 1) 1287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 13, 1) 1288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad days 1289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 2, 29) # no exception 1290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2004, 2, 29) # no exception 1291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2400, 2, 29) # no exception 1292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 2, 30) 1293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2001, 2, 29) 1294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2100, 2, 29) 1295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 1900, 2, 29) 1296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 1, 0) 1297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 1, 32) 1298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad hours 1299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 1, 31, 0) # no exception 1300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 1, 31, 23) # no exception 1301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 1, 31, -1) 1302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 24) 1303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad minutes 1304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 1, 31, 23, 0) # no exception 1305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 1, 31, 23, 59) # no exception 1306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, -1) 1307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 60) 1308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad seconds 1309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 1, 31, 23, 59, 0) # no exception 1310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 1, 31, 23, 59, 59) # no exception 1311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, -1) 1312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, 60) 1313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad microseconds 1314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 1, 31, 23, 59, 59, 0) # no exception 1315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2000, 1, 31, 23, 59, 59, 999999) # no exception 1316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 1317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2000, 1, 31, 23, 59, 59, -1) 1318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 1319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2000, 1, 31, 23, 59, 59, 1320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1000000) 1321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_hash_equality(self): 1323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2000, 12, 31, 23, 30, 17) 1324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh e = self.theclass(2000, 12, 31, 23, 30, 17) 1325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, e) 1326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(d), hash(e)) 1327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic = {d: 1} 1329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic[e] = 2 1330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(len(dic), 1) 1331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[d], 2) 1332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[e], 2) 1333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(2001, 1, 1, 0, 5, 17) 1335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh e = self.theclass(2001, 1, 1, 0, 5, 17) 1336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, e) 1337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(d), hash(e)) 1338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic = {d: 1} 1340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic[e] = 2 1341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(len(dic), 1) 1342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[d], 2) 1343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[e], 2) 1344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_computations(self): 1346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = self.theclass(2002, 1, 31) 1347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = self.theclass(1956, 1, 31) 1348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh diff = a-b 1349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4))) 1350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(diff.seconds, 0) 1351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(diff.microseconds, 0) 1352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = self.theclass(2002, 3, 2, 17, 6) 1353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh millisec = timedelta(0, 0, 1000) 1354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hour = timedelta(0, 3600) 1355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh day = timedelta(1) 1356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh week = timedelta(7) 1357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a + hour, self.theclass(2002, 3, 2, 18, 6)) 1358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hour + a, self.theclass(2002, 3, 2, 18, 6)) 1359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a + 10*hour, self.theclass(2002, 3, 3, 3, 6)) 1360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - hour, self.theclass(2002, 3, 2, 16, 6)) 1361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(-hour + a, self.theclass(2002, 3, 2, 16, 6)) 1362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - hour, a + -hour) 1363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - 20*hour, self.theclass(2002, 3, 1, 21, 6)) 1364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a + day, self.theclass(2002, 3, 3, 17, 6)) 1365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - day, self.theclass(2002, 3, 1, 17, 6)) 1366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a + week, self.theclass(2002, 3, 9, 17, 6)) 1367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - week, self.theclass(2002, 2, 23, 17, 6)) 1368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a + 52*week, self.theclass(2003, 3, 1, 17, 6)) 1369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - 52*week, self.theclass(2001, 3, 3, 17, 6)) 1370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a + week) - a, week) 1371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a + day) - a, day) 1372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a + hour) - a, hour) 1373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a + millisec) - a, millisec) 1374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a - week) - a, -week) 1375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a - day) - a, -day) 1376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a - hour) - a, -hour) 1377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual((a - millisec) - a, -millisec) 1378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a + week), -week) 1379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a + day), -day) 1380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a + hour), -hour) 1381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a + millisec), -millisec) 1382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a - week), week) 1383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a - day), day) 1384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a - hour), hour) 1385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (a - millisec), millisec) 1386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a + (week + day + hour + millisec), 1387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2002, 3, 10, 18, 6, 0, 1000)) 1388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a + (week + day + hour + millisec), 1389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (((a + week) + day) + hour) + millisec) 1390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (week + day + hour + millisec), 1391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(2002, 2, 22, 16, 5, 59, 999000)) 1392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a - (week + day + hour + millisec), 1393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (((a - week) - day) - hour) - millisec) 1394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Add/sub ints, longs, floats should be illegal 1395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in 1, 1L, 1.0: 1396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a+i) 1397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a-i) 1398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: i+a) 1399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: i-a) 1400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # delta - datetime is senseless. 1402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: day - a) 1403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # mixing datetime and (delta or datetime) via * or // is senseless 1404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: day * a) 1405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a * day) 1406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: day // a) 1407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a // day) 1408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a * a) 1409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a // a) 1410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # datetime + datetime is senseless 1411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: a + a) 1412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling(self): 1414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 6, 7, 23, 20, 59, 1, 64**2 1415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = self.theclass(*args) 1416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 1417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 1418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 1419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 1420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_more_pickling(self): 1422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = self.theclass(2003, 2, 7, 16, 48, 37, 444116) 1423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = pickle.dumps(a) 1424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = pickle.loads(s) 1425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.year, 2003) 1426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.month, 2) 1427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.day, 7) 1428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling_subclass_datetime(self): 1430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 6, 7, 23, 20, 59, 1, 64**2 1431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = SubclassDatetime(*args) 1432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 1433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 1434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 1435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 1436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_more_compare(self): 1438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The test_compare() inherited from TestDate covers the error cases. 1439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # We just want to test lexicographic ordering on the members datetime 1440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # has that date lacks. 1441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = [2000, 11, 29, 20, 58, 16, 999998] 1442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(*args) 1443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(*args) 1444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 == t2) 1445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 <= t2) 1446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 >= t2) 1447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 != t2) 1448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 < t2) 1449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 > t2) 1450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t1, t2), 0) 1451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t2, t1), 0) 1452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in range(len(args)): 1454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs = args[:] 1455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs[i] = args[i] + 1 1456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(*newargs) # this is larger than t1 1457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 < t2) 1458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 > t1) 1459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 <= t2) 1460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 >= t1) 1461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 != t2) 1462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 != t1) 1463ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 == t2) 1464ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 == t1) 1465ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 > t2) 1466ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 < t1) 1467ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 >= t2) 1468ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 <= t1) 1469ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t1, t2), -1) 1470ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t2, t1), 1) 1471ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1472ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1473ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # A helper for timestamp constructor tests. 1474ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def verify_field_equality(self, expected, got): 1475ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected.tm_year, got.year) 1476ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected.tm_mon, got.month) 1477ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected.tm_mday, got.day) 1478ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected.tm_hour, got.hour) 1479ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected.tm_min, got.minute) 1480ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected.tm_sec, got.second) 1481ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1482ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_fromtimestamp(self): 1483ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import time 1484ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1485ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ts = time.time() 1486ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = time.localtime(ts) 1487ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = self.theclass.fromtimestamp(ts) 1488ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.verify_field_equality(expected, got) 1489ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1490ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_utcfromtimestamp(self): 1491ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import time 1492ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1493ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ts = time.time() 1494ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = time.gmtime(ts) 1495ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = self.theclass.utcfromtimestamp(ts) 1496ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.verify_field_equality(expected, got) 1497ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1498ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_microsecond_rounding(self): 1499ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Test whether fromtimestamp "rounds up" floats that are less 1500ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # than one microsecond smaller than an integer. 1501ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(self.theclass.fromtimestamp(0.9999999), 1502ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass.fromtimestamp(1)) 1503ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1504ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_insane_fromtimestamp(self): 1505ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # It's possible that some platform maps time_t to double, 1506ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # and that this test will fail there. This test should 1507ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # exempt such platforms (provided they return reasonable 1508ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # results!). 1509ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for insane in -1e200, 1e200: 1510ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass.fromtimestamp, 1511ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh insane) 1512ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1513ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_insane_utcfromtimestamp(self): 1514ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # It's possible that some platform maps time_t to double, 1515ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # and that this test will fail there. This test should 1516ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # exempt such platforms (provided they return reasonable 1517ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # results!). 1518ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for insane in -1e200, 1e200: 1519ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass.utcfromtimestamp, 1520ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh insane) 1521ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps") 1522ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_negative_float_fromtimestamp(self): 1523ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The result is tz-dependent; at least test that this doesn't 1524ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # fail (like it did before bug 1646728 was fixed). 1525ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass.fromtimestamp(-1.05) 1526ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1527ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps") 1528ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_negative_float_utcfromtimestamp(self): 1529ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass.utcfromtimestamp(-1.05) 1530ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, self.theclass(1969, 12, 31, 23, 59, 58, 950000)) 1531ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1532ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_utcnow(self): 1533ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import time 1534ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1535ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Call it a success if utcnow() and utcfromtimestamp() are within 1536ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # a second of each other. 1537ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tolerance = timedelta(seconds=1) 1538ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dummy in range(3): 1539ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from_now = self.theclass.utcnow() 1540ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from_timestamp = self.theclass.utcfromtimestamp(time.time()) 1541ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if abs(from_timestamp - from_now) <= tolerance: 1542ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 1543ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Else try again a few times. 1544ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(abs(from_timestamp - from_now) <= tolerance) 1545ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1546ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_strptime(self): 1547ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import _strptime 1548ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1549ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh string = '2004-12-01 13:02:47.197' 1550ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh format = '%Y-%m-%d %H:%M:%S.%f' 1551ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result, frac = _strptime._strptime(string, format) 1552ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = self.theclass(*(result[0:6]+(frac,))) 1553ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = self.theclass.strptime(string, format) 1554ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 1555ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1556ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_more_timetuple(self): 1557ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This tests fields beyond those tested by the TestDate.test_timetuple. 1558ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(2004, 12, 31, 6, 22, 33) 1559ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.timetuple(), (2004, 12, 31, 6, 22, 33, 4, 366, -1)) 1560ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.timetuple(), 1561ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (t.year, t.month, t.day, 1562ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.hour, t.minute, t.second, 1563ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.weekday(), 1564ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.toordinal() - date(t.year, 1, 1).toordinal() + 1, 1565ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh -1)) 1566ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tt = t.timetuple() 1567ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(tt.tm_year, t.year) 1568ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(tt.tm_mon, t.month) 1569ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(tt.tm_mday, t.day) 1570ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(tt.tm_hour, t.hour) 1571ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(tt.tm_min, t.minute) 1572ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(tt.tm_sec, t.second) 1573ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(tt.tm_wday, t.weekday()) 1574ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(tt.tm_yday, t.toordinal() - 1575ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh date(t.year, 1, 1).toordinal() + 1) 1576ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(tt.tm_isdst, -1) 1577ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1578ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_more_strftime(self): 1579ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This tests fields beyond those tested by the TestDate.test_strftime. 1580ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(2004, 12, 31, 6, 22, 33, 47) 1581ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.strftime("%m %d %y %f %S %M %H %j"), 1582ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "12 31 04 000047 33 22 06 366") 1583ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1584ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_extract(self): 1585ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass(2002, 3, 4, 18, 45, 3, 1234) 1586ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.date(), date(2002, 3, 4)) 1587ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.time(), time(18, 45, 3, 1234)) 1588ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1589ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_combine(self): 1590ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = date(2002, 3, 4) 1591ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = time(18, 45, 3, 1234) 1592ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = self.theclass(2002, 3, 4, 18, 45, 3, 1234) 1593ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh combine = self.theclass.combine 1594ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = combine(d, t) 1595ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt, expected) 1596ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1597ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = combine(time=t, date=d) 1598ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt, expected) 1599ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1600ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, dt.date()) 1601ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t, dt.time()) 1602ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt, combine(dt.date(), dt.time())) 1603ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1604ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, combine) # need an arg 1605ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, combine, d) # need two args 1606ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, combine, t, d) # args reversed 1607ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, combine, d, t, 1) # too many args 1608ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, combine, "date", "time") # wrong types 1609ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1610ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_replace(self): 1611ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 1612ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = [1, 2, 3, 4, 5, 6, 7] 1613ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(*args) 1614ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(base, base.replace()) 1615ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1616ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = 0 1617ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for name, newval in (("year", 2), 1618ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("month", 3), 1619ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("day", 4), 1620ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("hour", 5), 1621ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("minute", 6), 1622ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("second", 7), 1623ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("microsecond", 8)): 1624ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs = args[:] 1625ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs[i] = newval 1626ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = cls(*newargs) 1627ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = base.replace(**{name: newval}) 1628ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 1629ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i += 1 1630ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1631ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Out of bounds. 1632ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(2000, 2, 29) 1633ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, year=2001) 1634ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1635ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_astimezone(self): 1636ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Pretty boring! The TZ test is more interesting here. astimezone() 1637ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # simply can't be applied to a naive object. 1638ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass.now() 1639ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f = FixedOffset(44, "") 1640ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, dt.astimezone) # not enough args 1641ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, dt.astimezone, f, f) # too many args 1642ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, dt.astimezone, dt) # arg wrong type 1643ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, dt.astimezone, f) # naive 1644ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, dt.astimezone, tz=f) # naive 1645ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1646ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class Bogus(tzinfo): 1647ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): return None 1648ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): return timedelta(0) 1649ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bog = Bogus() 1650ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, dt.astimezone, bog) # naive 1651ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1652ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class AlsoBogus(tzinfo): 1653ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): return timedelta(0) 1654ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): return None 1655ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh alsobog = AlsoBogus() 1656ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, dt.astimezone, alsobog) # also naive 1657ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1658ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_subclass_datetime(self): 1659ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1660ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class C(self.theclass): 1661ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theAnswer = 42 1662ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1663ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __new__(cls, *args, **kws): 1664ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh temp = kws.copy() 1665ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh extra = temp.pop('extra') 1666ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result = self.theclass.__new__(cls, *args, **temp) 1667ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result.extra = extra 1668ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return result 1669ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1670ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def newmeth(self, start): 1671ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return start + self.year + self.month + self.second 1672ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1673ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 2003, 4, 14, 12, 13, 41 1674ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1675ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt1 = self.theclass(*args) 1676ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = C(*args, **{'extra': 7}) 1677ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1678ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.__class__, C) 1679ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.theAnswer, 42) 1680ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.extra, 7) 1681ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt1.toordinal(), dt2.toordinal()) 1682ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month + 1683ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt1.second - 7) 1684ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1685ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass SubclassTime(time): 1686ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sub_var = 1 1687ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1688ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestTime(HarmlessMixedComparison, unittest.TestCase): 1689ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1690ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theclass = time 1691ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1692ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_basic_attributes(self): 1693ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(12, 0) 1694ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.hour, 12) 1695ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.minute, 0) 1696ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.second, 0) 1697ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.microsecond, 0) 1698ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1699ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_basic_attributes_nonzero(self): 1700ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make sure all attributes are non-zero so bugs in 1701ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bit-shifting access show up. 1702ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(12, 59, 59, 8000) 1703ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.hour, 12) 1704ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.minute, 59) 1705ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.second, 59) 1706ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.microsecond, 8000) 1707ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1708ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_roundtrip(self): 1709ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(1, 2, 3, 4) 1710ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1711ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Verify t -> string -> time identity. 1712ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = repr(t) 1713ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(s.startswith('datetime.')) 1714ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = s[9:] 1715ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = eval(s) 1716ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t, t2) 1717ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1718ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Verify identity via reconstructing from pieces. 1719ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(t.hour, t.minute, t.second, 1720ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.microsecond) 1721ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t, t2) 1722ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1723ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_comparing(self): 1724ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = [1, 2, 3, 4] 1725ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(*args) 1726ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(*args) 1727ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 == t2) 1728ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 <= t2) 1729ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 >= t2) 1730ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 != t2) 1731ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 < t2) 1732ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 > t2) 1733ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t1, t2), 0) 1734ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t2, t1), 0) 1735ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1736ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in range(len(args)): 1737ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs = args[:] 1738ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs[i] = args[i] + 1 1739ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(*newargs) # this is larger than t1 1740ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 < t2) 1741ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 > t1) 1742ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 <= t2) 1743ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 >= t1) 1744ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 != t2) 1745ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 != t1) 1746ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 == t2) 1747ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 == t1) 1748ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 > t2) 1749ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 < t1) 1750ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t1 >= t2) 1751ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t2 <= t1) 1752ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t1, t2), -1) 1753ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cmp(t2, t1), 1) 1754ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1755ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for badarg in OTHERSTUFF: 1756ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1 == badarg, False) 1757ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1 != badarg, True) 1758ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(badarg == t1, False) 1759ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(badarg != t1, True) 1760ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1761ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 <= badarg) 1762ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 < badarg) 1763ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 > badarg) 1764ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 >= badarg) 1765ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg <= t1) 1766ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg < t1) 1767ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg > t1) 1768ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: badarg >= t1) 1769ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1770ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bad_constructor_arguments(self): 1771ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad hours 1772ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(0, 0) # no exception 1773ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(23, 0) # no exception 1774ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, -1, 0) 1775ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 24, 0) 1776ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad minutes 1777ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(23, 0) # no exception 1778ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(23, 59) # no exception 1779ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 23, -1) 1780ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 23, 60) 1781ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad seconds 1782ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(23, 59, 0) # no exception 1783ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(23, 59, 59) # no exception 1784ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 23, 59, -1) 1785ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 23, 59, 60) 1786ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bad microseconds 1787ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(23, 59, 59, 0) # no exception 1788ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.theclass(23, 59, 59, 999999) # no exception 1789ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 23, 59, 59, -1) 1790ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, self.theclass, 23, 59, 59, 1000000) 1791ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1792ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_hash_equality(self): 1793ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(23, 30, 17) 1794ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh e = self.theclass(23, 30, 17) 1795ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, e) 1796ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(d), hash(e)) 1797ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1798ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic = {d: 1} 1799ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic[e] = 2 1800ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(len(dic), 1) 1801ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[d], 2) 1802ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[e], 2) 1803ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1804ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = self.theclass(0, 5, 17) 1805ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh e = self.theclass(0, 5, 17) 1806ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d, e) 1807ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(d), hash(e)) 1808ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1809ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic = {d: 1} 1810ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dic[e] = 2 1811ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(len(dic), 1) 1812ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[d], 2) 1813ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dic[e], 2) 1814ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1815ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_isoformat(self): 1816ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(4, 5, 1, 123) 1817ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "04:05:01.000123") 1818ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), str(t)) 1819ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1820ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass() 1821ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "00:00:00") 1822ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), str(t)) 1823ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1824ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(microsecond=1) 1825ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "00:00:00.000001") 1826ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), str(t)) 1827ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1828ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(microsecond=10) 1829ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "00:00:00.000010") 1830ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), str(t)) 1831ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1832ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(microsecond=100) 1833ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "00:00:00.000100") 1834ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), str(t)) 1835ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1836ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(microsecond=1000) 1837ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "00:00:00.001000") 1838ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), str(t)) 1839ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1840ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(microsecond=10000) 1841ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "00:00:00.010000") 1842ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), str(t)) 1843ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1844ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(microsecond=100000) 1845ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), "00:00:00.100000") 1846ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.isoformat(), str(t)) 1847ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1848ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_1653736(self): 1849ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # verify it doesn't accept extra keyword arguments 1850ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(second=1) 1851ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t.isoformat, foo=3) 1852ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1853ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_strftime(self): 1854ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(1, 2, 3, 4) 1855ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.strftime('%H %M %S %f'), "01 02 03 000004") 1856ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # A naive object replaces %z and %Z with empty strings. 1857ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''") 1858ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1859ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_format(self): 1860ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(1, 2, 3, 4) 1861ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.__format__(''), str(t)) 1862ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1863ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # check that a derived class's __str__() gets called 1864ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class A(self.theclass): 1865ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __str__(self): 1866ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'A' 1867ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = A(1, 2, 3, 4) 1868ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a.__format__(''), 'A') 1869ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1870ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # check that a derived class's strftime gets called 1871ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class B(self.theclass): 1872ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def strftime(self, format_spec): 1873ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'B' 1874ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = B(1, 2, 3, 4) 1875ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.__format__(''), str(t)) 1876ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1877ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for fmt in ['%H %M %S', 1878ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ]: 1879ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.__format__(fmt), t.strftime(fmt)) 1880ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(a.__format__(fmt), t.strftime(fmt)) 1881ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(b.__format__(fmt), 'B') 1882ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1883ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_str(self): 1884ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(self.theclass(1, 2, 3, 4)), "01:02:03.000004") 1885ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(self.theclass(10, 2, 3, 4000)), "10:02:03.004000") 1886ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(self.theclass(0, 2, 3, 400000)), "00:02:03.400000") 1887ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(self.theclass(12, 2, 3, 0)), "12:02:03") 1888ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(self.theclass(23, 15, 0, 0)), "23:15:00") 1889ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1890ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_repr(self): 1891ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh name = 'datetime.' + self.theclass.__name__ 1892ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(self.theclass(1, 2, 3, 4)), 1893ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "%s(1, 2, 3, 4)" % name) 1894ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(self.theclass(10, 2, 3, 4000)), 1895ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "%s(10, 2, 3, 4000)" % name) 1896ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(self.theclass(0, 2, 3, 400000)), 1897ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "%s(0, 2, 3, 400000)" % name) 1898ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(self.theclass(12, 2, 3, 0)), 1899ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "%s(12, 2, 3)" % name) 1900ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(self.theclass(23, 15, 0, 0)), 1901ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "%s(23, 15)" % name) 1902ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1903ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_resolution_info(self): 1904ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(self.theclass.min, self.theclass) 1905ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(self.theclass.max, self.theclass) 1906ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(self.theclass.resolution, timedelta) 1907ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(self.theclass.max > self.theclass.min) 1908ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1909ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling(self): 1910ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 20, 59, 16, 64**2 1911ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = self.theclass(*args) 1912ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 1913ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 1914ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 1915ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 1916ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1917ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling_subclass_time(self): 1918ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 20, 59, 16, 64**2 1919ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = SubclassTime(*args) 1920ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 1921ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 1922ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 1923ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 1924ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1925ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bool(self): 1926ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 1927ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(cls(1)) 1928ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(cls(0, 1)) 1929ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(cls(0, 0, 1)) 1930ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(cls(0, 0, 0, 1)) 1931ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not cls(0)) 1932ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not cls()) 1933ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1934ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_replace(self): 1935ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 1936ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = [1, 2, 3, 4] 1937ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(*args) 1938ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(base, base.replace()) 1939ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1940ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = 0 1941ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for name, newval in (("hour", 5), 1942ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("minute", 6), 1943ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("second", 7), 1944ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("microsecond", 8)): 1945ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs = args[:] 1946ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs[i] = newval 1947ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = cls(*newargs) 1948ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = base.replace(**{name: newval}) 1949ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 1950ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i += 1 1951ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1952ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Out of bounds. 1953ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(1) 1954ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, hour=24) 1955ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, minute=-1) 1956ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, second=100) 1957ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, microsecond=1000000) 1958ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1959ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_subclass_time(self): 1960ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1961ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class C(self.theclass): 1962ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theAnswer = 42 1963ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1964ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __new__(cls, *args, **kws): 1965ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh temp = kws.copy() 1966ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh extra = temp.pop('extra') 1967ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result = self.theclass.__new__(cls, *args, **temp) 1968ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result.extra = extra 1969ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return result 1970ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1971ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def newmeth(self, start): 1972ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return start + self.hour + self.second 1973ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1974ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 4, 5, 6 1975ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1976ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt1 = self.theclass(*args) 1977ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = C(*args, **{'extra': 7}) 1978ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1979ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.__class__, C) 1980ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.theAnswer, 42) 1981ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.extra, 7) 1982ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt1.isoformat(), dt2.isoformat()) 1983ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.second - 7) 1984ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1985ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_backdoor_resistance(self): 1986ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # see TestDate.test_backdoor_resistance(). 1987ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = '2:59.0' 1988ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for hour_byte in ' ', '9', chr(24), '\xff': 1989ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, self.theclass, 1990ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hour_byte + base[1:]) 1991ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1992ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# A mixin for classes with a tzinfo= argument. Subclasses must define 1993ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# theclass as a class atribute, and theclass(1, 1, 1, tzinfo=whatever) 1994ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# must be legit (which is true for time and datetime). 1995ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TZInfoBase: 1996ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1997ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_argument_passing(self): 1998ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 1999ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # A datetime passes itself on, a time passes None. 2000ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class introspective(tzinfo): 2001ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tzname(self, dt): return dt and "real" or "none" 2002ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): 2003ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return timedelta(minutes = dt and 42 or -42) 2004ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dst = utcoffset 2005ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2006ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh obj = cls(1, 2, 3, tzinfo=introspective()) 2007ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2008ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = cls is time and "none" or "real" 2009ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(obj.tzname(), expected) 2010ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2011ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = timedelta(minutes=(cls is time and -42 or 42)) 2012ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(obj.utcoffset(), expected) 2013ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(obj.dst(), expected) 2014ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2015ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bad_tzinfo_classes(self): 2016ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2017ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, cls, 1, 1, 1, tzinfo=12) 2018ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2019ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class NiceTry(object): 2020ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self): pass 2021ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): pass 2022ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, cls, 1, 1, 1, tzinfo=NiceTry) 2023ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2024ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class BetterTry(tzinfo): 2025ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self): pass 2026ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): pass 2027ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = BetterTry() 2028ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(1, 1, 1, tzinfo=b) 2029ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t.tzinfo is b) 2030ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2031ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_utc_offset_out_of_bounds(self): 2032ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class Edgy(tzinfo): 2033ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, offset): 2034ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.offset = timedelta(minutes=offset) 2035ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): 2036ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.offset 2037ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2038ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2039ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for offset, legit in ((-1440, False), 2040ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (-1439, True), 2041ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (1439, True), 2042ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (1440, False)): 2043ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if cls is time: 2044ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(1, 2, 3, tzinfo=Edgy(offset)) 2045ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif cls is datetime: 2046ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(6, 6, 6, 1, 2, 3, tzinfo=Edgy(offset)) 2047ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 2048ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh assert 0, "impossible" 2049ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if legit: 2050ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh aofs = abs(offset) 2051ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh h, m = divmod(aofs, 60) 2052ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tag = "%c%02d:%02d" % (offset < 0 and '-' or '+', h, m) 2053ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(t, datetime): 2054ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = t.timetz() 2055ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t), "01:02:03" + tag) 2056ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 2057ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, str, t) 2058ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2059ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_tzinfo_classes(self): 2060ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2061ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class C1(tzinfo): 2062ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): return None 2063ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): return None 2064ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tzname(self, dt): return None 2065ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for t in (cls(1, 1, 1), 2066ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls(1, 1, 1, tzinfo=None), 2067ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls(1, 1, 1, tzinfo=C1())): 2068ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t.utcoffset() is None) 2069ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t.dst() is None) 2070ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t.tzname() is None) 2071ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2072ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class C3(tzinfo): 2073ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): return timedelta(minutes=-1439) 2074ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): return timedelta(minutes=1439) 2075ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tzname(self, dt): return "aname" 2076ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(1, 1, 1, tzinfo=C3()) 2077ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.utcoffset(), timedelta(minutes=-1439)) 2078ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.dst(), timedelta(minutes=1439)) 2079ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tzname(), "aname") 2080ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2081ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Wrong types. 2082ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class C4(tzinfo): 2083ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): return "aname" 2084ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): return 7 2085ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tzname(self, dt): return 0 2086ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(1, 1, 1, tzinfo=C4()) 2087ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t.utcoffset) 2088ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t.dst) 2089ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t.tzname) 2090ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2091ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Offset out of range. 2092ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class C6(tzinfo): 2093ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): return timedelta(hours=-24) 2094ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): return timedelta(hours=24) 2095ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(1, 1, 1, tzinfo=C6()) 2096ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, t.utcoffset) 2097ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, t.dst) 2098ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2099ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Not a whole number of minutes. 2100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class C7(tzinfo): 2101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): return timedelta(seconds=61) 2102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): return timedelta(microseconds=-81) 2103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(1, 1, 1, tzinfo=C7()) 2104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, t.utcoffset) 2105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, t.dst) 2106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_aware_compare(self): 2108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure that utcoffset() gets ignored if the comparands have 2111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the same tzinfo member. 2112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class OperandDependentOffset(tzinfo): 2113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, t): 2114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if t.minute < 10: 2115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # d0 and d1 equal after adjustment 2116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return timedelta(minutes=t.minute) 2117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 2118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # d2 off in the weeds 2119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return timedelta(minutes=59) 2120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(8, 9, 10, tzinfo=OperandDependentOffset()) 2122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d0 = base.replace(minute=3) 2123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d1 = base.replace(minute=9) 2124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d2 = base.replace(minute=11) 2125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for x in d0, d1, d2: 2126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for y in d0, d1, d2: 2127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = cmp(x, y) 2128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = cmp(x.minute, y.minute) 2129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(got, expected) 2130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # However, if they're different members, uctoffset is not ignored. 2132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Note that a time can't actually have an operand-depedent offset, 2133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # though (and time.utcoffset() passes None to tzinfo.utcoffset()), 2134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # so skip this test for time. 2135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if cls is not time: 2136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d0 = base.replace(minute=3, tzinfo=OperandDependentOffset()) 2137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d1 = base.replace(minute=9, tzinfo=OperandDependentOffset()) 2138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d2 = base.replace(minute=11, tzinfo=OperandDependentOffset()) 2139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for x in d0, d1, d2: 2140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for y in d0, d1, d2: 2141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = cmp(x, y) 2142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if (x is d0 or x is d1) and (y is d0 or y is d1): 2143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = 0 2144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif x is y is d2: 2145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = 0 2146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif x is d2: 2147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = -1 2148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 2149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh assert y is d2 2150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = 1 2151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(got, expected) 2152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Testing time objects with a non-None tzinfo. 2155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase): 2156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theclass = time 2157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_empty(self): 2159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass() 2160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.hour, 0) 2161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.minute, 0) 2162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.second, 0) 2163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.microsecond, 0) 2164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t.tzinfo is None) 2165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_zones(self): 2167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh est = FixedOffset(-300, "EST", 1) 2168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh utc = FixedOffset(0, "UTC", -2) 2169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh met = FixedOffset(60, "MET", 3) 2170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = time( 7, 47, tzinfo=est) 2171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = time(12, 47, tzinfo=utc) 2172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t3 = time(13, 47, tzinfo=met) 2173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t4 = time(microsecond=40) 2174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t5 = time(microsecond=40, tzinfo=utc) 2175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.tzinfo, est) 2177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.tzinfo, utc) 2178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.tzinfo, met) 2179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t4.tzinfo is None) 2180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t5.tzinfo, utc) 2181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.utcoffset(), timedelta(minutes=-300)) 2183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.utcoffset(), timedelta(minutes=0)) 2184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.utcoffset(), timedelta(minutes=60)) 2185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t4.utcoffset() is None) 2186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t1.utcoffset, "no args") 2187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.tzname(), "EST") 2189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.tzname(), "UTC") 2190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.tzname(), "MET") 2191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t4.tzname() is None) 2192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t1.tzname, "no args") 2193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.dst(), timedelta(minutes=1)) 2195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.dst(), timedelta(minutes=-2)) 2196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.dst(), timedelta(minutes=3)) 2197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t4.dst() is None) 2198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t1.dst, "no args") 2199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(t1), hash(t2)) 2201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(t1), hash(t3)) 2202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(t2), hash(t3)) 2203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t3) 2206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2, t3) 2207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t4 == t5) # mixed tz-aware & naive 2208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t4 < t5) # mixed tz-aware & naive 2209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t5 < t4) # mixed tz-aware & naive 2210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t1), "07:47:00-05:00") 2212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t2), "12:47:00+00:00") 2213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t3), "13:47:00+01:00") 2214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t4), "00:00:00.000040") 2215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t5), "00:00:00.000040+00:00") 2216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.isoformat(), "07:47:00-05:00") 2218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.isoformat(), "12:47:00+00:00") 2219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.isoformat(), "13:47:00+01:00") 2220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t4.isoformat(), "00:00:00.000040") 2221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t5.isoformat(), "00:00:00.000040+00:00") 2222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = 'datetime.time' 2224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(t1), d + "(7, 47, tzinfo=est)") 2225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(t2), d + "(12, 47, tzinfo=utc)") 2226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(t3), d + "(13, 47, tzinfo=met)") 2227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(t4), d + "(0, 0, 0, 40)") 2228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(t5), d + "(0, 0, 0, 40, tzinfo=utc)") 2229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.strftime("%H:%M:%S %%Z=%Z %%z=%z"), 2231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "07:47:00 %Z=EST %z=-0500") 2232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.strftime("%H:%M:%S %Z %z"), "12:47:00 UTC +0000") 2233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.strftime("%H:%M:%S %Z %z"), "13:47:00 MET +0100") 2234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh yuck = FixedOffset(-1439, "%z %Z %%z%%Z") 2236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = time(23, 59, tzinfo=yuck) 2237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.strftime("%H:%M %%Z='%Z' %%z='%z'"), 2238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "23:59 %Z='%z %Z %%z%%Z' %z='-2359'") 2239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check that an invalid tzname result raises an exception. 2241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class Badtzname(tzinfo): 2242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tzname(self, dt): return 42 2243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = time(2, 3, 4, tzinfo=Badtzname()) 2244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.strftime("%H:%M:%S"), "02:03:04") 2245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, t.strftime, "%Z") 2246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_hash_edge_cases(self): 2248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Offsets that overflow a basic time. 2249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(0, 1, 2, 3, tzinfo=FixedOffset(1439, "")) 2250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(0, 0, 2, 3, tzinfo=FixedOffset(1438, "")) 2251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(t1), hash(t2)) 2252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(23, 58, 6, 100, tzinfo=FixedOffset(-1000, "")) 2254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(23, 48, 6, 100, tzinfo=FixedOffset(-1010, "")) 2255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(t1), hash(t2)) 2256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling(self): 2258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try one without a tzinfo. 2259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 20, 59, 16, 64**2 2260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = self.theclass(*args) 2261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 2262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 2263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 2264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 2265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try one with a tzinfo. 2267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tinfo = PicklableFixedOffset(-300, 'cookie') 2268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = self.theclass(5, 6, 7, tzinfo=tinfo) 2269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 2270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 2271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 2272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 2273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(derived.tzinfo, PicklableFixedOffset) 2274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(derived.utcoffset(), timedelta(minutes=-300)) 2275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(derived.tzname(), 'cookie') 2276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_more_bool(self): 2278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Test cases with non-None tzinfo. 2279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(0, tzinfo=FixedOffset(-300, "")) 2282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t) 2283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(5, tzinfo=FixedOffset(-300, "")) 2285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t) 2286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(5, tzinfo=FixedOffset(300, "")) 2288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t) 2289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(23, 59, tzinfo=FixedOffset(23*60 + 59, "")) 2291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not t) 2292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Mostly ensuring this doesn't overflow internally. 2294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(0, tzinfo=FixedOffset(23*60 + 59, "")) 2295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t) 2296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # But this should yield a value error -- the utcoffset is bogus. 2298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(0, tzinfo=FixedOffset(24*60, "")) 2299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, lambda: bool(t)) 2300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Likewise. 2302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = cls(0, tzinfo=FixedOffset(-24*60, "")) 2303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, lambda: bool(t)) 2304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_replace(self): 2306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh z100 = FixedOffset(100, "+100") 2308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh zm200 = FixedOffset(timedelta(minutes=-200), "-200") 2309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = [1, 2, 3, 4, z100] 2310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(*args) 2311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(base, base.replace()) 2312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = 0 2314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for name, newval in (("hour", 5), 2315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("minute", 6), 2316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("second", 7), 2317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("microsecond", 8), 2318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("tzinfo", zm200)): 2319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs = args[:] 2320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs[i] = newval 2321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = cls(*newargs) 2322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = base.replace(**{name: newval}) 2323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 2324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i += 1 2325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure we can get rid of a tzinfo. 2327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(base.tzname(), "+100") 2328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base2 = base.replace(tzinfo=None) 2329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(base2.tzinfo is None) 2330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(base2.tzname() is None) 2331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure we can add one. 2333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base3 = base2.replace(tzinfo=z100) 2334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(base, base3) 2335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(base.tzinfo is base3.tzinfo) 2336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Out of bounds. 2338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(1) 2339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, hour=24) 2340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, minute=-1) 2341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, second=100) 2342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, microsecond=1000000) 2343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_mixed_compare(self): 2345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = time(1, 2, 3) 2346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = time(1, 2, 3) 2347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = t2.replace(tzinfo=None) 2349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = t2.replace(tzinfo=FixedOffset(None, "")) 2351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = t2.replace(tzinfo=FixedOffset(0, "")) 2353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 == t2) 2354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # In time w/ identical tzinfo objects, utcoffset is ignored. 2356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class Varies(tzinfo): 2357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self): 2358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.offset = timedelta(minutes=22) 2359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, t): 2360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.offset += timedelta(minutes=1) 2361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.offset 2362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh v = Varies() 2364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = t2.replace(tzinfo=v) 2365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = t2.replace(tzinfo=v) 2366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.utcoffset(), timedelta(minutes=23)) 2367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.utcoffset(), timedelta(minutes=24)) 2368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # But if they're not identical, it isn't ignored. 2371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = t2.replace(tzinfo=Varies()) 2372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 < t2) # t1's offset counter still going up 2373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_subclass_timetz(self): 2375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class C(self.theclass): 2377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theAnswer = 42 2378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __new__(cls, *args, **kws): 2380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh temp = kws.copy() 2381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh extra = temp.pop('extra') 2382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result = self.theclass.__new__(cls, *args, **temp) 2383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result.extra = extra 2384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return result 2385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def newmeth(self, start): 2387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return start + self.hour + self.second 2388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 4, 5, 6, 500, FixedOffset(-300, "EST", 1) 2390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt1 = self.theclass(*args) 2392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = C(*args, **{'extra': 7}) 2393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.__class__, C) 2395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.theAnswer, 42) 2396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.extra, 7) 2397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt1.utcoffset(), dt2.utcoffset()) 2398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.second - 7) 2399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Testing datetime objects with a non-None tzinfo. 2402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestDateTimeTZ(TestDateTime, TZInfoBase, unittest.TestCase): 2404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theclass = datetime 2405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_trivial(self): 2407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass(1, 2, 3, 4, 5, 6, 7) 2408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.year, 1) 2409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.month, 2) 2410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.day, 3) 2411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.hour, 4) 2412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.minute, 5) 2413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.second, 6) 2414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.microsecond, 7) 2415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.tzinfo, None) 2416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_even_more_compare(self): 2418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The test_compare() and test_more_compare() inherited from TestDate 2419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # and TestDateTime covered non-tzinfo cases. 2420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Smallest possible after UTC adjustment. 2422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(1, 1, 1, tzinfo=FixedOffset(1439, "")) 2423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Largest possible after UTC adjustment. 2424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999999, 2425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tzinfo=FixedOffset(-1439, "")) 2426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make sure those compare correctly, and w/o overflow. 2428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 < t2) 2429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 != t2) 2430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 > t1) 2431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 == t1) 2433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t2 == t2) 2434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Equal afer adjustment. 2436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(1, "")) 2437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(2, 1, 1, 3, 13, tzinfo=FixedOffset(3*60+13+2, "")) 2438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Change t1 not to subtract a minute, and t1 should be larger. 2441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(0, "")) 2442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 > t2) 2443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Change t1 to subtract 2 minutes, and t1 should be smaller. 2445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(2, "")) 2446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 < t2) 2447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Back to the original t1, but make seconds resolve it. 2449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(1, ""), 2450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh second=1) 2451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 > t2) 2452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Likewise, but make microseconds resolve it. 2454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(1, ""), 2455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh microsecond=1) 2456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 > t2) 2457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make t2 naive and it should fail. 2459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass.min 2460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 == t2) 2461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2, t2) 2462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2463ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # It's also naive if it has tzinfo but tzinfo.utcoffset() is None. 2464ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class Naive(tzinfo): 2465ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): return None 2466ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(5, 6, 7, tzinfo=Naive()) 2467ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 == t2) 2468ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2, t2) 2469ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2470ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # OTOH, it's OK to compare two of these mixing the two ways of being 2471ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # naive. 2472ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(5, 6, 7) 2473ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2474ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2475ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try a bogus uctoffset. 2476ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class Bogus(tzinfo): 2477ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): 2478ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return timedelta(minutes=1440) # out of bounds 2479ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = self.theclass(2, 2, 2, tzinfo=Bogus()) 2480ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = self.theclass(2, 2, 2, tzinfo=FixedOffset(0, "")) 2481ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, lambda: t1 == t2) 2482ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2483ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_pickling(self): 2484ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try one without a tzinfo. 2485ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 6, 7, 23, 20, 59, 1, 64**2 2486ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = self.theclass(*args) 2487ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 2488ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 2489ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 2490ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 2491ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2492ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try one with a tzinfo. 2493ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tinfo = PicklableFixedOffset(-300, 'cookie') 2494ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig = self.theclass(*args, **{'tzinfo': tinfo}) 2495ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = self.theclass(1, 1, 1, tzinfo=FixedOffset(0, "", 0)) 2496ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for pickler, unpickler, proto in pickle_choices: 2497ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh green = pickler.dumps(orig, proto) 2498ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh derived = unpickler.loads(green) 2499ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(orig, derived) 2500ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(derived.tzinfo, PicklableFixedOffset) 2501ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(derived.utcoffset(), timedelta(minutes=-300)) 2502ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(derived.tzname(), 'cookie') 2503ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2504ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_extreme_hashes(self): 2505ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If an attempt is made to hash these via subtracting the offset 2506ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # then hashing a datetime object, OverflowError results. The 2507ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Python implementation used to blow up here. 2508ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(1, 1, 1, tzinfo=FixedOffset(1439, "")) 2509ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hash(t) 2510ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999999, 2511ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tzinfo=FixedOffset(-1439, "")) 2512ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hash(t) 2513ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2514ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # OTOH, an OOB offset should blow up. 2515ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.theclass(5, 5, 5, tzinfo=FixedOffset(-1440, "")) 2516ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, hash, t) 2517ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2518ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_zones(self): 2519ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh est = FixedOffset(-300, "EST") 2520ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh utc = FixedOffset(0, "UTC") 2521ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh met = FixedOffset(60, "MET") 2522ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = datetime(2002, 3, 19, 7, 47, tzinfo=est) 2523ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = datetime(2002, 3, 19, 12, 47, tzinfo=utc) 2524ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t3 = datetime(2002, 3, 19, 13, 47, tzinfo=met) 2525ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.tzinfo, est) 2526ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.tzinfo, utc) 2527ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.tzinfo, met) 2528ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.utcoffset(), timedelta(minutes=-300)) 2529ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.utcoffset(), timedelta(minutes=0)) 2530ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.utcoffset(), timedelta(minutes=60)) 2531ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.tzname(), "EST") 2532ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.tzname(), "UTC") 2533ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t3.tzname(), "MET") 2534ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(t1), hash(t2)) 2535ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(t1), hash(t3)) 2536ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(hash(t2), hash(t3)) 2537ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2538ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t3) 2539ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2, t3) 2540ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t1), "2002-03-19 07:47:00-05:00") 2541ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t2), "2002-03-19 12:47:00+00:00") 2542ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t3), "2002-03-19 13:47:00+01:00") 2543ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = 'datetime.datetime(2002, 3, 19, ' 2544ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(t1), d + "7, 47, tzinfo=est)") 2545ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(t2), d + "12, 47, tzinfo=utc)") 2546ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(t3), d + "13, 47, tzinfo=met)") 2547ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2548ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_combine(self): 2549ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh met = FixedOffset(60, "MET") 2550ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = date(2002, 3, 4) 2551ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tz = time(18, 45, 3, 1234, tzinfo=met) 2552ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = datetime.combine(d, tz) 2553ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt, datetime(2002, 3, 4, 18, 45, 3, 1234, 2554ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tzinfo=met)) 2555ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2556ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_extract(self): 2557ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh met = FixedOffset(60, "MET") 2558ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass(2002, 3, 4, 18, 45, 3, 1234, tzinfo=met) 2559ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.date(), date(2002, 3, 4)) 2560ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.time(), time(18, 45, 3, 1234)) 2561ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.timetz(), time(18, 45, 3, 1234, tzinfo=met)) 2562ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2563ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_tz_aware_arithmetic(self): 2564ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import random 2565ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2566ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh now = self.theclass.now() 2567ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tz55 = FixedOffset(-330, "west 5:30") 2568ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timeaware = now.time().replace(tzinfo=tz55) 2569ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nowaware = self.theclass.combine(now.date(), timeaware) 2570ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(nowaware.tzinfo is tz55) 2571ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(nowaware.timetz(), timeaware) 2572ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2573ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Can't mix aware and non-aware. 2574ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: now - nowaware) 2575ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: nowaware - now) 2576ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2577ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # And adding datetime's doesn't make sense, aware or not. 2578ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: now + nowaware) 2579ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: nowaware + now) 2580ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: nowaware + nowaware) 2581ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2582ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Subtracting should yield 0. 2583ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(now - now, timedelta(0)) 2584ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(nowaware - nowaware, timedelta(0)) 2585ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2586ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Adding a delta should preserve tzinfo. 2587ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh delta = timedelta(weeks=1, minutes=12, microseconds=5678) 2588ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nowawareplus = nowaware + delta 2589ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(nowaware.tzinfo is tz55) 2590ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nowawareplus2 = delta + nowaware 2591ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(nowawareplus2.tzinfo is tz55) 2592ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(nowawareplus, nowawareplus2) 2593ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2594ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # that - delta should be what we started with, and that - what we 2595ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # started with should be delta. 2596ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh diff = nowawareplus - delta 2597ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(diff.tzinfo is tz55) 2598ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(nowaware, diff) 2599ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: delta - nowawareplus) 2600ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(nowawareplus - nowaware, delta) 2601ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2602ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make up a random timezone. 2603ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tzr = FixedOffset(random.randrange(-1439, 1440), "randomtimezone") 2604ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Attach it to nowawareplus. 2605ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nowawareplus = nowawareplus.replace(tzinfo=tzr) 2606ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(nowawareplus.tzinfo is tzr) 2607ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make sure the difference takes the timezone adjustments into account. 2608ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = nowaware - nowawareplus 2609ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Expected: (nowaware base - nowaware offset) - 2610ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # (nowawareplus base - nowawareplus offset) = 2611ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # (nowaware base - nowawareplus base) + 2612ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # (nowawareplus offset - nowaware offset) = 2613ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # -delta + nowawareplus offset - nowaware offset 2614ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = nowawareplus.utcoffset() - nowaware.utcoffset() - delta 2615ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(got, expected) 2616ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2617ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try max possible difference. 2618ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh min = self.theclass(1, 1, 1, tzinfo=FixedOffset(1439, "min")) 2619ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh max = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999999, 2620ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tzinfo=FixedOffset(-1439, "max")) 2621ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh maxdiff = max - min 2622ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(maxdiff, self.theclass.max - self.theclass.min + 2623ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timedelta(minutes=2*1439)) 2624ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2625ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_tzinfo_now(self): 2626ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh meth = self.theclass.now 2627ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up). 2628ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = meth() 2629ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try with and without naming the keyword. 2630ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh off42 = FixedOffset(42, "42") 2631ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh another = meth(off42) 2632ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh again = meth(tz=off42) 2633ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(another.tzinfo is again.tzinfo) 2634ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(another.utcoffset(), timedelta(minutes=42)) 2635ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Bad argument with and w/o naming the keyword. 2636ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, 16) 2637ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, tzinfo=16) 2638ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Bad keyword name. 2639ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, tinfo=off42) 2640ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Too many args. 2641ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, off42, off42) 2642ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2643ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # We don't know which time zone we're in, and don't have a tzinfo 2644ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # class to represent it, so seeing whether a tz argument actually 2645ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # does a conversion is tricky. 2646ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh weirdtz = FixedOffset(timedelta(hours=15, minutes=58), "weirdtz", 0) 2647ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh utc = FixedOffset(0, "utc", 0) 2648ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dummy in range(3): 2649ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh now = datetime.now(weirdtz) 2650ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(now.tzinfo is weirdtz) 2651ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh utcnow = datetime.utcnow().replace(tzinfo=utc) 2652ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh now2 = utcnow.astimezone(weirdtz) 2653ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if abs(now - now2) < timedelta(seconds=30): 2654ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 2655ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Else the code is broken, or more than 30 seconds passed between 2656ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # calls; assuming the latter, just try again. 2657ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 2658ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Three strikes and we're out. 2659ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail("utcnow(), now(tz), or astimezone() may be broken") 2660ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2661ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_tzinfo_fromtimestamp(self): 2662ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import time 2663ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh meth = self.theclass.fromtimestamp 2664ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ts = time.time() 2665ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up). 2666ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = meth(ts) 2667ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try with and without naming the keyword. 2668ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh off42 = FixedOffset(42, "42") 2669ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh another = meth(ts, off42) 2670ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh again = meth(ts, tz=off42) 2671ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(another.tzinfo is again.tzinfo) 2672ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(another.utcoffset(), timedelta(minutes=42)) 2673ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Bad argument with and w/o naming the keyword. 2674ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, ts, 16) 2675ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, ts, tzinfo=16) 2676ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Bad keyword name. 2677ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, ts, tinfo=off42) 2678ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Too many args. 2679ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, ts, off42, off42) 2680ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Too few args. 2681ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth) 2682ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2683ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try to make sure tz= actually does some conversion. 2684ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timestamp = 1000000000 2685ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh utcdatetime = datetime.utcfromtimestamp(timestamp) 2686ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # In POSIX (epoch 1970), that's 2001-09-09 01:46:40 UTC, give or take. 2687ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # But on some flavor of Mac, it's nowhere near that. So we can't have 2688ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # any idea here what time that actually is, we can only test that 2689ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # relative changes match. 2690ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh utcoffset = timedelta(hours=-15, minutes=39) # arbitrary, but not zero 2691ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tz = FixedOffset(utcoffset, "tz", 0) 2692ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = utcdatetime + utcoffset 2693ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = datetime.fromtimestamp(timestamp, tz) 2694ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got.replace(tzinfo=None)) 2695ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2696ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_tzinfo_utcnow(self): 2697ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh meth = self.theclass.utcnow 2698ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up). 2699ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = meth() 2700ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try with and without naming the keyword; for whatever reason, 2701ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # utcnow() doesn't accept a tzinfo argument. 2702ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh off42 = FixedOffset(42, "42") 2703ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, off42) 2704ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, tzinfo=off42) 2705ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2706ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_tzinfo_utcfromtimestamp(self): 2707ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import time 2708ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh meth = self.theclass.utcfromtimestamp 2709ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ts = time.time() 2710ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up). 2711ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = meth(ts) 2712ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try with and without naming the keyword; for whatever reason, 2713ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # utcfromtimestamp() doesn't accept a tzinfo argument. 2714ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh off42 = FixedOffset(42, "42") 2715ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, ts, off42) 2716ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, meth, ts, tzinfo=off42) 2717ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2718ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_tzinfo_timetuple(self): 2719ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # TestDateTime tested most of this. datetime adds a twist to the 2720ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # DST flag. 2721ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class DST(tzinfo): 2722ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, dstvalue): 2723ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(dstvalue, int): 2724ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dstvalue = timedelta(minutes=dstvalue) 2725ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.dstvalue = dstvalue 2726ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): 2727ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.dstvalue 2728ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2729ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2730ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dstvalue, flag in (-33, 1), (33, 1), (0, 0), (None, -1): 2731ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = cls(1, 1, 1, 10, 20, 30, 40, tzinfo=DST(dstvalue)) 2732ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = d.timetuple() 2733ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(1, t.tm_year) 2734ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(1, t.tm_mon) 2735ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(1, t.tm_mday) 2736ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(10, t.tm_hour) 2737ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(20, t.tm_min) 2738ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(30, t.tm_sec) 2739ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(0, t.tm_wday) 2740ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(1, t.tm_yday) 2741ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(flag, t.tm_isdst) 2742ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2743ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # dst() returns wrong type. 2744ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, cls(1, 1, 1, tzinfo=DST("x")).timetuple) 2745ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2746ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # dst() at the edge. 2747ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cls(1,1,1, tzinfo=DST(1439)).timetuple().tm_isdst, 1) 2748ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(cls(1,1,1, tzinfo=DST(-1439)).timetuple().tm_isdst, 1) 2749ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2750ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # dst() out of range. 2751ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, cls(1,1,1, tzinfo=DST(1440)).timetuple) 2752ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, cls(1,1,1, tzinfo=DST(-1440)).timetuple) 2753ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2754ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_utctimetuple(self): 2755ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class DST(tzinfo): 2756ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, dstvalue): 2757ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(dstvalue, int): 2758ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dstvalue = timedelta(minutes=dstvalue) 2759ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.dstvalue = dstvalue 2760ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): 2761ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.dstvalue 2762ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2763ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2764ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This can't work: DST didn't implement utcoffset. 2765ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(NotImplementedError, 2766ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls(1, 1, 1, tzinfo=DST(0)).utcoffset) 2767ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2768ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class UOFS(DST): 2769ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, uofs, dofs=None): 2770ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh DST.__init__(self, dofs) 2771ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.uofs = timedelta(minutes=uofs) 2772ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): 2773ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.uofs 2774ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2775ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure tm_isdst is 0 regardless of what dst() says: DST is never 2776ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # in effect for a UTC time. 2777ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dstvalue in -33, 33, 0, None: 2778ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=UOFS(-53, dstvalue)) 2779ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = d.utctimetuple() 2780ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.year, t.tm_year) 2781ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.month, t.tm_mon) 2782ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.day, t.tm_mday) 2783ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(11, t.tm_hour) # 20mm + 53mm = 1hn + 13mm 2784ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(13, t.tm_min) 2785ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.second, t.tm_sec) 2786ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.weekday(), t.tm_wday) 2787ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.toordinal() - date(1, 1, 1).toordinal() + 1, 2788ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.tm_yday) 2789ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(0, t.tm_isdst) 2790ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2791ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # At the edges, UTC adjustment can normalize into years out-of-range 2792ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # for a datetime object. Ensure that a correct timetuple is 2793ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # created anyway. 2794ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tiny = cls(MINYEAR, 1, 1, 0, 0, 37, tzinfo=UOFS(1439)) 2795ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # That goes back 1 minute less than a full day. 2796ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = tiny.utctimetuple() 2797ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_year, MINYEAR-1) 2798ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_mon, 12) 2799ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_mday, 31) 2800ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_hour, 0) 2801ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_min, 1) 2802ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_sec, 37) 2803ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_yday, 366) # "year 0" is a leap year 2804ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_isdst, 0) 2805ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2806ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh huge = cls(MAXYEAR, 12, 31, 23, 59, 37, 999999, tzinfo=UOFS(-1439)) 2807ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # That goes forward 1 minute less than a full day. 2808ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = huge.utctimetuple() 2809ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_year, MAXYEAR+1) 2810ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_mon, 1) 2811ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_mday, 1) 2812ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_hour, 23) 2813ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_min, 58) 2814ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_sec, 37) 2815ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_yday, 1) 2816ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t.tm_isdst, 0) 2817ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2818ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_tzinfo_isoformat(self): 2819ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh zero = FixedOffset(0, "+00:00") 2820ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh plus = FixedOffset(220, "+03:40") 2821ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh minus = FixedOffset(-231, "-03:51") 2822ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh unknown = FixedOffset(None, "") 2823ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2824ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2825ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh datestr = '0001-02-03' 2826ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for ofs in None, zero, plus, minus, unknown: 2827ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for us in 0, 987001: 2828ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = cls(1, 2, 3, 4, 5, 59, us, tzinfo=ofs) 2829ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timestr = '04:05:59' + (us and '.987001' or '') 2830ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ofsstr = ofs is not None and d.tzname() or '' 2831ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tailstr = timestr + ofsstr 2832ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh iso = d.isoformat() 2833ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(iso, datestr + 'T' + tailstr) 2834ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(iso, d.isoformat('T')) 2835ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(d.isoformat('k'), datestr + 'k' + tailstr) 2836ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(d), datestr + ' ' + tailstr) 2837ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2838ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_replace(self): 2839ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2840ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh z100 = FixedOffset(100, "+100") 2841ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh zm200 = FixedOffset(timedelta(minutes=-200), "-200") 2842ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = [1, 2, 3, 4, 5, 6, 7, z100] 2843ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(*args) 2844ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(base, base.replace()) 2845ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2846ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i = 0 2847ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for name, newval in (("year", 2), 2848ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("month", 3), 2849ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("day", 4), 2850ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("hour", 5), 2851ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("minute", 6), 2852ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("second", 7), 2853ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("microsecond", 8), 2854ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("tzinfo", zm200)): 2855ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs = args[:] 2856ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newargs[i] = newval 2857ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = cls(*newargs) 2858ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = base.replace(**{name: newval}) 2859ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 2860ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh i += 1 2861ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2862ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure we can get rid of a tzinfo. 2863ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(base.tzname(), "+100") 2864ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base2 = base.replace(tzinfo=None) 2865ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(base2.tzinfo is None) 2866ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(base2.tzname() is None) 2867ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2868ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure we can add one. 2869ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base3 = base2.replace(tzinfo=z100) 2870ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(base, base3) 2871ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(base.tzinfo is base3.tzinfo) 2872ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2873ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Out of bounds. 2874ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(2000, 2, 29) 2875ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, base.replace, year=2001) 2876ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2877ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_more_astimezone(self): 2878ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The inherited test_astimezone covered some trivial and error cases. 2879ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fnone = FixedOffset(None, "None") 2880ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f44m = FixedOffset(44, "44") 2881ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fm5h = FixedOffset(-timedelta(hours=5), "m300") 2882ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2883ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = self.theclass.now(tz=f44m) 2884ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(dt.tzinfo is f44m) 2885ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Replacing with degenerate tzinfo raises an exception. 2886ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, dt.astimezone, fnone) 2887ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ditto with None tz. 2888ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, dt.astimezone, None) 2889ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Replacing with same tzinfo makes no change. 2890ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh x = dt.astimezone(dt.tzinfo) 2891ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(x.tzinfo is f44m) 2892ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(x.date(), dt.date()) 2893ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(x.time(), dt.time()) 2894ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2895ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Replacing with different tzinfo does adjust. 2896ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = dt.astimezone(fm5h) 2897ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(got.tzinfo is fm5h) 2898ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(got.utcoffset(), timedelta(hours=-5)) 2899ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = dt - dt.utcoffset() # in effect, convert to UTC 2900ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected += fm5h.utcoffset(dt) # and from there to local time 2901ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = expected.replace(tzinfo=fm5h) # and attach new tzinfo 2902ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(got.date(), expected.date()) 2903ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(got.time(), expected.time()) 2904ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(got.timetz(), expected.timetz()) 2905ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(got.tzinfo is expected.tzinfo) 2906ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(got, expected) 2907ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2908ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_aware_subtract(self): 2909ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cls = self.theclass 2910ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2911ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure that utcoffset() is ignored when the operands have the 2912ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # same tzinfo member. 2913ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class OperandDependentOffset(tzinfo): 2914ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, t): 2915ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if t.minute < 10: 2916ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # d0 and d1 equal after adjustment 2917ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return timedelta(minutes=t.minute) 2918ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 2919ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # d2 off in the weeds 2920ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return timedelta(minutes=59) 2921ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2922ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(8, 9, 10, 11, 12, 13, 14, tzinfo=OperandDependentOffset()) 2923ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d0 = base.replace(minute=3) 2924ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d1 = base.replace(minute=9) 2925ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d2 = base.replace(minute=11) 2926ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for x in d0, d1, d2: 2927ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for y in d0, d1, d2: 2928ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = x - y 2929ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = timedelta(minutes=x.minute - y.minute) 2930ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(got, expected) 2931ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2932ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # OTOH, if the tzinfo members are distinct, utcoffsets aren't 2933ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignored. 2934ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh base = cls(8, 9, 10, 11, 12, 13, 14) 2935ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d0 = base.replace(minute=3, tzinfo=OperandDependentOffset()) 2936ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d1 = base.replace(minute=9, tzinfo=OperandDependentOffset()) 2937ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d2 = base.replace(minute=11, tzinfo=OperandDependentOffset()) 2938ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for x in d0, d1, d2: 2939ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for y in d0, d1, d2: 2940ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = x - y 2941ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if (x is d0 or x is d1) and (y is d0 or y is d1): 2942ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = timedelta(0) 2943ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif x is y is d2: 2944ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = timedelta(0) 2945ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif x is d2: 2946ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = timedelta(minutes=(11-59)-0) 2947ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 2948ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh assert y is d2 2949ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = timedelta(minutes=0-(11-59)) 2950ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(got, expected) 2951ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2952ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_mixed_compare(self): 2953ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = datetime(1, 2, 3, 4, 5, 6, 7) 2954ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = datetime(1, 2, 3, 4, 5, 6, 7) 2955ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2956ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = t2.replace(tzinfo=None) 2957ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2958ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = t2.replace(tzinfo=FixedOffset(None, "")) 2959ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2960ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = t2.replace(tzinfo=FixedOffset(0, "")) 2961ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: t1 == t2) 2962ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2963ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # In datetime w/ identical tzinfo objects, utcoffset is ignored. 2964ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class Varies(tzinfo): 2965ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self): 2966ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.offset = timedelta(minutes=22) 2967ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, t): 2968ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.offset += timedelta(minutes=1) 2969ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.offset 2970ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2971ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh v = Varies() 2972ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = t2.replace(tzinfo=v) 2973ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = t2.replace(tzinfo=v) 2974ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1.utcoffset(), timedelta(minutes=23)) 2975ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2.utcoffset(), timedelta(minutes=24)) 2976ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, t2) 2977ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2978ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # But if they're not identical, it isn't ignored. 2979ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = t2.replace(tzinfo=Varies()) 2980ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(t1 < t2) # t1's offset counter still going up 2981ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2982ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_subclass_datetimetz(self): 2983ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2984ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class C(self.theclass): 2985ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theAnswer = 42 2986ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2987ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __new__(cls, *args, **kws): 2988ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh temp = kws.copy() 2989ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh extra = temp.pop('extra') 2990ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result = self.theclass.__new__(cls, *args, **temp) 2991ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result.extra = extra 2992ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return result 2993ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2994ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def newmeth(self, start): 2995ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return start + self.hour + self.year 2996ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2997ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args = 2002, 12, 31, 4, 5, 6, 500, FixedOffset(-300, "EST", 1) 2998ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 2999ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt1 = self.theclass(*args) 3000ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt2 = C(*args, **{'extra': 7}) 3001ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3002ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.__class__, C) 3003ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.theAnswer, 42) 3004ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.extra, 7) 3005ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt1.utcoffset(), dt2.utcoffset()) 3006ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.year - 7) 3007ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3008ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Pain to set up DST-aware tzinfo classes. 3009ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3010ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef first_sunday_on_or_after(dt): 3011ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh days_to_go = 6 - dt.weekday() 3012ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if days_to_go: 3013ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt += timedelta(days_to_go) 3014ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return dt 3015ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3016ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehZERO = timedelta(0) 3017ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehHOUR = timedelta(hours=1) 3018ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehDAY = timedelta(days=1) 3019ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# In the US, DST starts at 2am (standard time) on the first Sunday in April. 3020ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehDSTSTART = datetime(1, 4, 1, 2) 3021ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# and ends at 2am (DST time; 1am standard time) on the last Sunday of Oct, 3022ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# which is the first Sunday on or after Oct 25. Because we view 1:MM as 3023ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# being standard time on that day, there is no spelling in local time of 3024ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# the last hour of DST (that's 1:MM DST, but 1:MM is taken as standard time). 3025ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehDSTEND = datetime(1, 10, 25, 1) 3026ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3027ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass USTimeZone(tzinfo): 3028ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3029ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, hours, reprname, stdname, dstname): 3030ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdoffset = timedelta(hours=hours) 3031ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.reprname = reprname 3032ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.stdname = stdname 3033ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.dstname = dstname 3034ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3035ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __repr__(self): 3036ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.reprname 3037ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3038ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tzname(self, dt): 3039ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.dst(dt): 3040ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.dstname 3041ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 3042ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.stdname 3043ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3044ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): 3045ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.stdoffset + self.dst(dt) 3046ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3047ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): 3048ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if dt is None or dt.tzinfo is None: 3049ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # An exception instead may be sensible here, in one or more of 3050ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the cases. 3051ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return ZERO 3052ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh assert dt.tzinfo is self 3053ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3054ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Find first Sunday in April. 3055ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year)) 3056ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh assert start.weekday() == 6 and start.month == 4 and start.day <= 7 3057ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3058ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Find last Sunday in October. 3059ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh end = first_sunday_on_or_after(DSTEND.replace(year=dt.year)) 3060ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh assert end.weekday() == 6 and end.month == 10 and end.day >= 25 3061ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3062ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Can't compare naive to aware objects, so strip the timezone from 3063ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # dt first. 3064ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if start <= dt.replace(tzinfo=None) < end: 3065ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return HOUR 3066ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 3067ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return ZERO 3068ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3069ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehEastern = USTimeZone(-5, "Eastern", "EST", "EDT") 3070ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehCentral = USTimeZone(-6, "Central", "CST", "CDT") 3071ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehMountain = USTimeZone(-7, "Mountain", "MST", "MDT") 3072ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehPacific = USTimeZone(-8, "Pacific", "PST", "PDT") 3073ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehutc_real = FixedOffset(0, "UTC", 0) 3074ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# For better test coverage, we want another flavor of UTC that's west of 3075ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# the Eastern and Pacific timezones. 3076ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehutc_fake = FixedOffset(-12*60, "UTCfake", 0) 3077ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3078ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestTimezoneConversions(unittest.TestCase): 3079ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The DST switch times for 2002, in std time. 3080ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dston = datetime(2002, 4, 7, 2) 3081ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dstoff = datetime(2002, 10, 27, 1) 3082ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3083ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh theclass = datetime 3084ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3085ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check a time that's inside DST. 3086ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def checkinside(self, dt, tz, utc, dston, dstoff): 3087ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.dst(), HOUR) 3088ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3089ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Conversion to our own timezone is always an identity. 3090ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.astimezone(tz), dt) 3091ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3092ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh asutc = dt.astimezone(utc) 3093ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh there_and_back = asutc.astimezone(tz) 3094ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3095ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Conversion to UTC and back isn't always an identity here, 3096ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # because there are redundant spellings (in local time) of 3097ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # UTC time when DST begins: the clock jumps from 1:59:59 3098ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # to 3:00:00, and a local time of 2:MM:SS doesn't really 3099ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # make sense then. The classes above treat 2:MM:SS as 3100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # daylight time then (it's "after 2am"), really an alias 3101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # for 1:MM:SS standard time. The latter form is what 3102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # conversion back from UTC produces. 3103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if dt.date() == dston.date() and dt.hour == 2: 3104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # We're in the redundant hour, and coming back from 3105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # UTC gives the 1:MM:SS standard-time spelling. 3106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(there_and_back + HOUR, dt) 3107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Although during was considered to be in daylight 3108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # time, there_and_back is not. 3109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(there_and_back.dst(), ZERO) 3110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # They're the same times in UTC. 3111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(there_and_back.astimezone(utc), 3112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt.astimezone(utc)) 3113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 3114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # We're not in the redundant hour. 3115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt, there_and_back) 3116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Because we have a redundant spelling when DST begins, there is 3118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # (unfortunately) an hour when DST ends that can't be spelled at all in 3119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # local time. When DST ends, the clock jumps from 1:59 back to 1:00 3120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # again. The hour 1:MM DST has no spelling then: 1:MM is taken to be 3121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # standard time. 1:MM DST == 0:MM EST, but 0:MM is taken to be 3122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # daylight time. The hour 1:MM daylight == 0:MM standard can't be 3123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # expressed in local time. Nevertheless, we want conversion back 3124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # from UTC to mimic the local clock's "repeat an hour" behavior. 3125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nexthour_utc = asutc + HOUR 3126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nexthour_tz = nexthour_utc.astimezone(tz) 3127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if dt.date() == dstoff.date() and dt.hour == 0: 3128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # We're in the hour before the last DST hour. The last DST hour 3129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # is ineffable. We want the conversion back to repeat 1:MM. 3130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(nexthour_tz, dt.replace(hour=1)) 3131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nexthour_utc += HOUR 3132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nexthour_tz = nexthour_utc.astimezone(tz) 3133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(nexthour_tz, dt.replace(hour=1)) 3134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 3135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(nexthour_tz - dt, HOUR) 3136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check a time that's outside DST. 3138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def checkoutside(self, dt, tz, utc): 3139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.dst(), ZERO) 3140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Conversion to our own timezone is always an identity. 3142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt.astimezone(tz), dt) 3143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Converting to UTC and back is an identity too. 3145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh asutc = dt.astimezone(utc) 3146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh there_and_back = asutc.astimezone(tz) 3147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(dt, there_and_back) 3148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def convert_between_tz_and_utc(self, tz, utc): 3150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dston = self.dston.replace(tzinfo=tz) 3151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Because 1:MM on the day DST ends is taken as being standard time, 3152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # there is no spelling in tz for the last hour of daylight time. 3153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # For purposes of the test, the last hour of DST is 0:MM, which is 3154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # taken as being daylight time (and 1:MM is taken as being standard 3155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # time). 3156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dstoff = self.dstoff.replace(tzinfo=tz) 3157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for delta in (timedelta(weeks=13), 3158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh DAY, 3159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh HOUR, 3160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timedelta(minutes=1), 3161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timedelta(microseconds=1)): 3162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.checkinside(dston, tz, utc, dston, dstoff) 3164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for during in dston + delta, dstoff - delta: 3165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.checkinside(during, tz, utc, dston, dstoff) 3166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.checkoutside(dstoff, tz, utc) 3168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for outside in dston - delta, dstoff + delta: 3169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.checkoutside(outside, tz, utc) 3170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_easy(self): 3172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Despite the name of this test, the endcases are excruciating. 3173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.convert_between_tz_and_utc(Eastern, utc_real) 3174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.convert_between_tz_and_utc(Pacific, utc_real) 3175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.convert_between_tz_and_utc(Eastern, utc_fake) 3176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.convert_between_tz_and_utc(Pacific, utc_fake) 3177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The next is really dancing near the edge. It works because 3178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Pacific and Eastern are far enough apart that their "problem 3179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # hours" don't overlap. 3180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.convert_between_tz_and_utc(Eastern, Pacific) 3181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.convert_between_tz_and_utc(Pacific, Eastern) 3182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # OTOH, these fail! Don't enable them. The difficulty is that 3183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the edge case tests assume that every hour is representable in 3184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the "utc" class. This is always true for a fixed-offset tzinfo 3185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # class (lke utc_real and utc_fake), but not for Eastern or Central. 3186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # For these adjacent DST-aware time zones, the range of time offsets 3187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # tested ends up creating hours in the one that aren't representable 3188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # in the other. For the same reason, we would see failures in the 3189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Eastern vs Pacific tests too if we added 3*HOUR to the list of 3190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # offset deltas in convert_between_tz_and_utc(). 3191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 3192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # self.convert_between_tz_and_utc(Eastern, Central) # can't work 3193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # self.convert_between_tz_and_utc(Central, Eastern) # can't work 3194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_tricky(self): 3196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 22:00 on day before daylight starts. 3197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fourback = self.dston - timedelta(hours=4) 3198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ninewest = FixedOffset(-9*60, "-0900", 0) 3199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fourback = fourback.replace(tzinfo=ninewest) 3200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 22:00-0900 is 7:00 UTC == 2:00 EST == 3:00 DST. Since it's "after 3201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 2", we should get the 3 spelling. 3202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If we plug 22:00 the day before into Eastern, it "looks like std 3203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # time", so its offset is returned as -5, and -5 - -9 = 4. Adding 4 3204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # to 22:00 lands on 2:00, which makes no sense in local time (the 3205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # local clock jumps from 1 to 3). The point here is to make sure we 3206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # get the 3 spelling. 3207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = self.dston.replace(hour=3) 3208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = fourback.astimezone(Eastern).replace(tzinfo=None) 3209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 3210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Similar, but map to 6:00 UTC == 1:00 EST == 2:00 DST. In that 3212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # case we want the 1:00 spelling. 3213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sixutc = self.dston.replace(hour=6, tzinfo=utc_real) 3214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Now 6:00 "looks like daylight", so the offset wrt Eastern is -4, 3215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # and adding -4-0 == -4 gives the 2:00 spelling. We want the 1:00 EST 3216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # spelling. 3217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = self.dston.replace(hour=1) 3218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = sixutc.astimezone(Eastern).replace(tzinfo=None) 3219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 3220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Now on the day DST ends, we want "repeat an hour" behavior. 3222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # UTC 4:MM 5:MM 6:MM 7:MM checking these 3223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # EST 23:MM 0:MM 1:MM 2:MM 3224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # EDT 0:MM 1:MM 2:MM 3:MM 3225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # wall 0:MM 1:MM 1:MM 2:MM against these 3226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for utc in utc_real, utc_fake: 3227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for tz in Eastern, Pacific: 3228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh first_std_hour = self.dstoff - timedelta(hours=2) # 23:MM 3229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert that to UTC. 3230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh first_std_hour -= tz.utcoffset(None) 3231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Adjust for possibly fake UTC. 3232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh asutc = first_std_hour + utc.utcoffset(None) 3233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # First UTC hour to convert; this is 4:00 when utc=utc_real & 3234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # tz=Eastern. 3235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh asutcbase = asutc.replace(tzinfo=utc) 3236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for tzhour in (0, 1, 1, 2): 3237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expectedbase = self.dstoff.replace(hour=tzhour) 3238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for minute in 0, 30, 59: 3239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = expectedbase.replace(minute=minute) 3240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh asutc = asutcbase.replace(minute=minute) 3241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh astz = asutc.astimezone(tz) 3242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(astz.replace(tzinfo=None), expected) 3243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh asutcbase += HOUR 3244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bogus_dst(self): 3247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class ok(tzinfo): 3248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def utcoffset(self, dt): return HOUR 3249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): return HOUR 3250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh now = self.theclass.now().replace(tzinfo=utc_real) 3252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Doesn't blow up. 3253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh now.astimezone(ok()) 3254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Does blow up. 3256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class notok(ok): 3257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dst(self, dt): return None 3258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, now.astimezone, notok()) 3259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_fromutc(self): 3261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, Eastern.fromutc) # not enough args 3262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh now = datetime.utcnow().replace(tzinfo=utc_real) 3263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(ValueError, Eastern.fromutc, now) # wrong tzinfo 3264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh now = now.replace(tzinfo=Eastern) # insert correct tzinfo 3265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh enow = Eastern.fromutc(now) # doesn't blow up 3266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(enow.tzinfo, Eastern) # has right tzinfo member 3267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, Eastern.fromutc, now, now) # too many args 3268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, Eastern.fromutc, date.today()) # wrong type 3269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Always converts UTC to standard time. 3271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class FauxUSTimeZone(USTimeZone): 3272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def fromutc(self, dt): 3273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return dt + self.stdoffset 3274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh FEastern = FauxUSTimeZone(-5, "FEastern", "FEST", "FEDT") 3275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # UTC 4:MM 5:MM 6:MM 7:MM 8:MM 9:MM 3277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # EST 23:MM 0:MM 1:MM 2:MM 3:MM 4:MM 3278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # EDT 0:MM 1:MM 2:MM 3:MM 4:MM 5:MM 3279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check around DST start. 3281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh start = self.dston.replace(hour=4, tzinfo=Eastern) 3282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fstart = start.replace(tzinfo=FEastern) 3283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for wall in 23, 0, 1, 3, 4, 5: 3284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = start.replace(hour=wall) 3285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if wall == 23: 3286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected -= timedelta(days=1) 3287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = Eastern.fromutc(start) 3288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 3289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = fstart + FEastern.stdoffset 3291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = FEastern.fromutc(fstart) 3292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 3293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure astimezone() calls fromutc() too. 3295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = fstart.replace(tzinfo=utc_real).astimezone(FEastern) 3296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 3297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh start += HOUR 3299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fstart += HOUR 3300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check around DST end. 3302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh start = self.dstoff.replace(hour=4, tzinfo=Eastern) 3303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fstart = start.replace(tzinfo=FEastern) 3304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for wall in 0, 1, 1, 2, 3, 4: 3305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = start.replace(hour=wall) 3306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = Eastern.fromutc(start) 3307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 3308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected = fstart + FEastern.stdoffset 3310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = FEastern.fromutc(fstart) 3311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 3312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure astimezone() calls fromutc() too. 3314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh got = fstart.replace(tzinfo=utc_real).astimezone(FEastern) 3315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(expected, got) 3316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh start += HOUR 3318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fstart += HOUR 3319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh############################################################################# 3322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# oddballs 3323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass Oddballs(unittest.TestCase): 3325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bug_1028306(self): 3327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Trying to compare a date to a datetime should act like a mixed- 3328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # type comparison, despite that datetime is a subclass of date. 3329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh as_date = date.today() 3330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh as_datetime = datetime.combine(as_date, time()) 3331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(as_date != as_datetime) 3332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(as_datetime != as_date) 3333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not as_date == as_datetime) 3334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not as_datetime == as_date) 3335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: as_date < as_datetime) 3336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: as_datetime < as_date) 3337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: as_date <= as_datetime) 3338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: as_datetime <= as_date) 3339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: as_date > as_datetime) 3340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: as_datetime > as_date) 3341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: as_date >= as_datetime) 3342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, lambda: as_datetime >= as_date) 3343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Neverthelss, comparison should work with the base-class (date) 3345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # projection if use of a date method is forced. 3346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(as_date.__eq__(as_datetime)) 3347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh different_day = (as_date.day + 1) % 20 + 1 3348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(not as_date.__eq__(as_datetime.replace(day= 3349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh different_day))) 3350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # And date should compare with other subclasses of date. If a 3352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # subclass wants to stop this, it's up to the subclass to do so. 3353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh date_sc = SubclassDate(as_date.year, as_date.month, as_date.day) 3354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(as_date, date_sc) 3355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(date_sc, as_date) 3356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ditto for datetimes. 3358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh datetime_sc = SubclassDatetime(as_datetime.year, as_datetime.month, 3359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh as_date.day, 0, 0, 0) 3360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(as_datetime, datetime_sc) 3361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(datetime_sc, as_datetime) 3362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef test_main(): 3364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh test_support.run_unittest(__name__) 3365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == "__main__": 3367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh test_main() 3368