1515from datetime import timedelta
1616from datetime import tzinfo
1717from datetime import time
18+ from datetime import timezone
1819from datetime import date , datetime
1920
2021pickle_choices = [(pickle , pickle , proto ) for proto in range (3 )]
@@ -49,6 +50,7 @@ def test_constants(self):
4950# tzinfo tests
5051
5152class FixedOffset (tzinfo ):
53+
5254 def __init__ (self , offset , name , dstoffset = 42 ):
5355 if isinstance (offset , int ):
5456 offset = timedelta (minutes = offset )
@@ -67,6 +69,7 @@ def dst(self, dt):
6769 return self .__dstoffset
6870
6971class PicklableFixedOffset (FixedOffset ):
72+
7073 def __init__ (self , offset = None , name = None , dstoffset = None ):
7174 FixedOffset .__init__ (self , offset , name , dstoffset )
7275
@@ -131,6 +134,97 @@ def test_pickling_subclass(self):
131134 self .assertEqual (derived .utcoffset (None ), offset )
132135 self .assertEqual (derived .tzname (None ), 'cookie' )
133136
137+ class TestTimeZone (unittest .TestCase ):
138+
139+ def setUp (self ):
140+ self .ACDT = timezone (timedelta (hours = 9.5 ), 'ACDT' )
141+ self .EST = timezone (- timedelta (hours = 5 ), 'EST' )
142+ self .DT = datetime (2010 , 1 , 1 )
143+
144+ def test_str (self ):
145+ for tz in [self .ACDT , self .EST , timezone .utc ,
146+ timezone .min , timezone .max ]:
147+ self .assertEqual (str (tz ), tz .tzname (None ))
148+
149+ def test_class_members (self ):
150+ limit = timedelta (hours = 23 , minutes = 59 )
151+ self .assertEquals (timezone .utc .utcoffset (None ), ZERO )
152+ self .assertEquals (timezone .min .utcoffset (None ), - limit )
153+ self .assertEquals (timezone .max .utcoffset (None ), limit )
154+
155+
156+ def test_constructor (self ):
157+ self .assertEquals (timezone .utc , timezone (timedelta (0 )))
158+ # invalid offsets
159+ for invalid in [timedelta (microseconds = 1 ), timedelta (1 , 1 ),
160+ timedelta (seconds = 1 ), timedelta (1 ), - timedelta (1 )]:
161+ self .assertRaises (ValueError , timezone , invalid )
162+ self .assertRaises (ValueError , timezone , - invalid )
163+
164+ with self .assertRaises (TypeError ): timezone (None )
165+ with self .assertRaises (TypeError ): timezone (42 )
166+ with self .assertRaises (TypeError ): timezone (ZERO , None )
167+ with self .assertRaises (TypeError ): timezone (ZERO , 42 )
168+
169+ def test_inheritance (self ):
170+ self .assertTrue (isinstance (timezone .utc , tzinfo ))
171+ self .assertTrue (isinstance (self .EST , tzinfo ))
172+
173+ def test_utcoffset (self ):
174+ dummy = self .DT
175+ for h in [0 , 1.5 , 12 ]:
176+ offset = h * HOUR
177+ self .assertEquals (offset , timezone (offset ).utcoffset (dummy ))
178+ self .assertEquals (- offset , timezone (- offset ).utcoffset (dummy ))
179+
180+ with self .assertRaises (TypeError ): self .EST .utcoffset ('' )
181+ with self .assertRaises (TypeError ): self .EST .utcoffset (5 )
182+
183+
184+ def test_dst (self ):
185+ self .assertEquals (None , timezone .utc .dst (self .DT ))
186+
187+ with self .assertRaises (TypeError ): self .EST .dst ('' )
188+ with self .assertRaises (TypeError ): self .EST .dst (5 )
189+
190+ def test_tzname (self ):
191+ self .assertEquals ('UTC+00:00' , timezone (ZERO ).tzname (None ))
192+ self .assertEquals ('UTC-05:00' , timezone (- 5 * HOUR ).tzname (None ))
193+ self .assertEquals ('UTC+09:30' , timezone (9.5 * HOUR ).tzname (None ))
194+ self .assertEquals ('UTC-00:01' , timezone (timedelta (minutes = - 1 )).tzname (None ))
195+ self .assertEquals ('XYZ' , timezone (- 5 * HOUR , 'XYZ' ).tzname (None ))
196+
197+ with self .assertRaises (TypeError ): self .EST .tzname ('' )
198+ with self .assertRaises (TypeError ): self .EST .tzname (5 )
199+
200+ def test_fromutc (self ):
201+ with self .assertRaises (ValueError ):
202+ timezone .utc .fromutc (self .DT )
203+ for tz in [self .EST , self .ACDT , Eastern ]:
204+ utctime = self .DT .replace (tzinfo = tz )
205+ local = tz .fromutc (utctime )
206+ self .assertEquals (local - utctime , tz .utcoffset (local ))
207+ self .assertEquals (local ,
208+ self .DT .replace (tzinfo = timezone .utc ))
209+
210+ def test_comparison (self ):
211+ self .assertNotEqual (timezone (ZERO ), timezone (HOUR ))
212+ self .assertEqual (timezone (HOUR ), timezone (HOUR ))
213+ self .assertEqual (timezone (- 5 * HOUR ), timezone (- 5 * HOUR , 'EST' ))
214+ with self .assertRaises (TypeError ): timezone (ZERO ) < timezone (ZERO )
215+ self .assertIn (timezone (ZERO ), {timezone (ZERO )})
216+
217+ def test_aware_datetime (self ):
218+ # test that timezone instances can be used by datetime
219+ t = datetime (1 , 1 , 1 )
220+ for tz in [timezone .min , timezone .max , timezone .utc ]:
221+ self .assertEquals (tz .tzname (t ),
222+ t .replace (tzinfo = tz ).tzname ())
223+ self .assertEquals (tz .utcoffset (t ),
224+ t .replace (tzinfo = tz ).utcoffset ())
225+ self .assertEquals (tz .dst (t ),
226+ t .replace (tzinfo = tz ).dst ())
227+
134228#############################################################################
135229# Base clase for testing a particular aspect of timedelta, time, date and
136230# datetime comparisons.
@@ -2729,20 +2823,21 @@ def test_tzinfo_now(self):
27292823 # We don't know which time zone we're in, and don't have a tzinfo
27302824 # class to represent it, so seeing whether a tz argument actually
27312825 # does a conversion is tricky.
2732- weirdtz = FixedOffset (timedelta (hours = 15 , minutes = 58 ), "weirdtz" , 0 )
27332826 utc = FixedOffset (0 , "utc" , 0 )
2734- for dummy in range (3 ):
2735- now = datetime .now (weirdtz )
2736- self .assertTrue (now .tzinfo is weirdtz )
2737- utcnow = datetime .utcnow ().replace (tzinfo = utc )
2738- now2 = utcnow .astimezone (weirdtz )
2739- if abs (now - now2 ) < timedelta (seconds = 30 ):
2740- break
2741- # Else the code is broken, or more than 30 seconds passed between
2742- # calls; assuming the latter, just try again.
2743- else :
2744- # Three strikes and we're out.
2745- self .fail ("utcnow(), now(tz), or astimezone() may be broken" )
2827+ for weirdtz in [FixedOffset (timedelta (hours = 15 , minutes = 58 ), "weirdtz" , 0 ),
2828+ timezone (timedelta (hours = 15 , minutes = 58 ), "weirdtz" ),]:
2829+ for dummy in range (3 ):
2830+ now = datetime .now (weirdtz )
2831+ self .assertTrue (now .tzinfo is weirdtz )
2832+ utcnow = datetime .utcnow ().replace (tzinfo = utc )
2833+ now2 = utcnow .astimezone (weirdtz )
2834+ if abs (now - now2 ) < timedelta (seconds = 30 ):
2835+ break
2836+ # Else the code is broken, or more than 30 seconds passed between
2837+ # calls; assuming the latter, just try again.
2838+ else :
2839+ # Three strikes and we're out.
2840+ self .fail ("utcnow(), now(tz), or astimezone() may be broken" )
27462841
27472842 def test_tzinfo_fromtimestamp (self ):
27482843 import time
0 commit comments