~ubuntu-branches/ubuntu/trusty/python-tz/trusty-updates

« back to all changes in this revision

Viewing changes to pytz/test_tzinfo.py

  • Committer: Bazaar Package Importer
  • Author(s): Brian Sutherland
  • Date: 2005-02-08 02:14:33 UTC
  • Revision ID: james.westby@ubuntu.com-20050208021433-t6c9teignwsm2ywo
Tags: upstream-2005a
ImportĀ upstreamĀ versionĀ 2005a

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# -*- coding: ascii -*-
 
3
'''
 
4
$Id: test_tzinfo.py,v 1.9 2004/10/25 04:14:00 zenzen Exp $
 
5
'''
 
6
 
 
7
__rcs_id__  = '$Id: test_tzinfo.py,v 1.9 2004/10/25 04:14:00 zenzen Exp $'
 
8
__version__ = '$Revision: 1.9 $'[11:-2]
 
9
 
 
10
import sys, os
 
11
sys.path.insert(0, os.pardir)
 
12
 
 
13
import unittest, doctest
 
14
from datetime import datetime, tzinfo, timedelta
 
15
import pytz, reference
 
16
 
 
17
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
 
18
 
 
19
NOTIME = timedelta(0)
 
20
 
 
21
UTC = pytz.timezone('UTC')
 
22
REF_UTC = reference.UTC
 
23
 
 
24
class BasicTest(unittest.TestCase):
 
25
    def testUTC(self):
 
26
        now = datetime.now(tz=UTC)
 
27
        self.failUnless(now.utcoffset() == NOTIME)
 
28
        self.failUnless(now.dst() == NOTIME)
 
29
        self.failUnless(now.timetuple() == now.utctimetuple())
 
30
 
 
31
    def testReferenceUTC(self):
 
32
        now = datetime.now(tz=REF_UTC)
 
33
        self.failUnless(now.utcoffset() == NOTIME)
 
34
        self.failUnless(now.dst() == NOTIME)
 
35
        self.failUnless(now.timetuple() == now.utctimetuple())
 
36
 
 
37
 
 
38
class USEasternDSTStartTestCase(unittest.TestCase):
 
39
    tzinfo = pytz.timezone('US/Eastern')
 
40
 
 
41
    # 24 hours before DST changeover
 
42
    transition_time = datetime(2002, 4, 7, 7, 0, 0, tzinfo=UTC)
 
43
 
 
44
    # Increase for 'flexible' DST transitions due to 1 minute granularity
 
45
    # of Python's datetime library
 
46
    instant = timedelta(seconds=1)
 
47
 
 
48
    # before transition
 
49
    before = {
 
50
        'tzname': 'EST',
 
51
        'utcoffset': timedelta(hours = -5),
 
52
        'dst': timedelta(hours = 0),
 
53
        }
 
54
 
 
55
    # after transition
 
56
    after = {
 
57
        'tzname': 'EDT',
 
58
        'utcoffset': timedelta(hours = -4),
 
59
        'dst': timedelta(hours = 1),
 
60
        }
 
61
 
 
62
    def _test_tzname(self, utc_dt, wanted):
 
63
        dt = utc_dt.astimezone(self.tzinfo)
 
64
        self.failUnlessEqual(dt.tzname(),wanted['tzname'],
 
65
            'Expected %s as tzname for %s. Got %s' % (
 
66
                wanted['tzname'],str(utc_dt),dt.tzname()
 
67
                )
 
68
            )
 
69
 
 
70
    def _test_utcoffset(self, utc_dt, wanted):
 
71
        utcoffset = wanted['utcoffset']
 
72
        dt = utc_dt.astimezone(self.tzinfo)
 
73
        self.failUnlessEqual(
 
74
                dt.utcoffset(),utcoffset,
 
75
                'Expected %s as utcoffset for %s. Got %s' % (
 
76
                    utcoffset,utc_dt,dt.utcoffset()
 
77
                    )
 
78
                )
 
79
        return
 
80
        dt_wanted = utc_dt.replace(tzinfo=None) + utcoffset
 
81
        dt_got = dt.replace(tzinfo=None)
 
82
        self.failUnlessEqual(
 
83
                dt_wanted,
 
84
                dt_got,
 
85
                'Got %s. Wanted %s' % (str(dt_got),str(dt_wanted))
 
86
                )
 
87
 
 
88
    def _test_dst(self, utc_dt, wanted):
 
89
        dst = wanted['dst']
 
90
        dt = utc_dt.astimezone(self.tzinfo)
 
91
        self.failUnlessEqual(dt.dst(),dst,
 
92
            'Expected %s as dst for %s. Got %s' % (
 
93
                dst,utc_dt,dt.dst()
 
94
                )
 
95
            )
 
96
 
 
97
    def test_arithmetic(self):
 
98
        utc_dt = self.transition_time
 
99
 
 
100
        for days in range(-420, 720, 20):
 
101
            delta = timedelta(days=days)
 
102
 
 
103
            # Make sure we can get back where we started
 
104
            dt = utc_dt.astimezone(self.tzinfo)
 
105
            dt2 = dt + delta
 
106
            dt2 = dt2 - delta
 
107
            self.failUnlessEqual(dt, dt2)
 
108
 
 
109
            # Make sure arithmetic crossing DST boundaries ends
 
110
            # up in the correct timezone after normalization
 
111
            self.failUnlessEqual(
 
112
                    (utc_dt + delta).astimezone(self.tzinfo).strftime(fmt),
 
113
                    self.tzinfo.normalize(dt + delta).strftime(fmt),
 
114
                    'Incorrect result for delta==%d days.  Wanted %r. Got %r'%(
 
115
                        days,
 
116
                        (utc_dt + delta).astimezone(self.tzinfo).strftime(fmt),
 
117
                        self.tzinfo.normalize(dt + delta).strftime(fmt),
 
118
                        )
 
119
                    )
 
120
 
 
121
    def _test_all(self, utc_dt, wanted):
 
122
        self._test_utcoffset(utc_dt, wanted)
 
123
        self._test_tzname(utc_dt, wanted)
 
124
        self._test_dst(utc_dt, wanted)
 
125
 
 
126
    def testDayBefore(self):
 
127
        self._test_all(
 
128
                self.transition_time - timedelta(days=1), self.before
 
129
                )
 
130
 
 
131
    def testTwoHoursBefore(self):
 
132
        self._test_all(
 
133
                self.transition_time - timedelta(hours=2), self.before
 
134
                )
 
135
 
 
136
    def testHourBefore(self):
 
137
        self._test_all(
 
138
                self.transition_time - timedelta(hours=1), self.before
 
139
                )
 
140
 
 
141
    def testInstantBefore(self):
 
142
        self._test_all(
 
143
                self.transition_time - self.instant, self.before
 
144
                )
 
145
 
 
146
    def testTransition(self):
 
147
        self._test_all(
 
148
                self.transition_time, self.after
 
149
                )
 
150
 
 
151
    def testInstantAfter(self):
 
152
        self._test_all(
 
153
                self.transition_time + self.instant, self.after
 
154
                )
 
155
 
 
156
    def testHourAfter(self):
 
157
        self._test_all(
 
158
                self.transition_time + timedelta(hours=1), self.after
 
159
                )
 
160
 
 
161
    def testTwoHoursAfter(self):
 
162
        self._test_all(
 
163
                self.transition_time + timedelta(hours=1), self.after
 
164
                )
 
165
 
 
166
    def testDayAfter(self):
 
167
        self._test_all(
 
168
                self.transition_time + timedelta(days=1), self.after
 
169
                )
 
170
 
 
171
 
 
172
class USEasternDSTEndTestCase(USEasternDSTStartTestCase):
 
173
    tzinfo = pytz.timezone('US/Eastern')
 
174
    transition_time = datetime(2002, 10, 27, 6, 0, 0, tzinfo=UTC)
 
175
    before = {
 
176
        'tzname': 'EDT',
 
177
        'utcoffset': timedelta(hours = -4),
 
178
        'dst': timedelta(hours = 1),
 
179
        }
 
180
    after = {
 
181
        'tzname': 'EST',
 
182
        'utcoffset': timedelta(hours = -5),
 
183
        'dst': timedelta(hours = 0),
 
184
        }
 
185
 
 
186
 
 
187
class USEasternEPTStartTestCase(USEasternDSTStartTestCase):
 
188
    transition_time = datetime(1945, 8, 14, 23, 0, 0, tzinfo=UTC)
 
189
    before = {
 
190
        'tzname': 'EWT',
 
191
        'utcoffset': timedelta(hours = -4),
 
192
        'dst': timedelta(hours = 1),
 
193
        }
 
194
    after = {
 
195
        'tzname': 'EPT',
 
196
        'utcoffset': timedelta(hours = -4),
 
197
        'dst': timedelta(hours = 1),
 
198
        }
 
199
 
 
200
 
 
201
class USEasternEPTEndTestCase(USEasternDSTStartTestCase):
 
202
    transition_time = datetime(1945, 9, 30, 6, 0, 0, tzinfo=UTC)
 
203
    before = {
 
204
        'tzname': 'EPT',
 
205
        'utcoffset': timedelta(hours = -4),
 
206
        'dst': timedelta(hours = 1),
 
207
        }
 
208
    after = {
 
209
        'tzname': 'EST',
 
210
        'utcoffset': timedelta(hours = -5),
 
211
        'dst': timedelta(hours = 0),
 
212
        }
 
213
 
 
214
 
 
215
class WarsawWMTEndTestCase(USEasternDSTStartTestCase):
 
216
    # In 1915, Warsaw changed from Warsaw to Central European time.
 
217
    # This involved the clocks being set backwards, causing a end-of-DST
 
218
    # like situation without DST being involved.
 
219
    tzinfo = pytz.timezone('Europe/Warsaw')
 
220
    transition_time = datetime(1915, 8, 4, 22, 36, 0, tzinfo=UTC)
 
221
    before = {
 
222
        'tzname': 'WMT',
 
223
        'utcoffset': timedelta(hours=1, minutes=24),
 
224
        'dst': timedelta(0),
 
225
        }
 
226
    after = {
 
227
        'tzname': 'CET',
 
228
        'utcoffset': timedelta(hours=1),
 
229
        'dst': timedelta(0),
 
230
        }
 
231
 
 
232
 
 
233
class VilniusWMTEndTestCase(USEasternDSTStartTestCase):
 
234
    # At the end of 1916, Vilnius changed timezones putting its clock
 
235
    # forward by 11 minutes 35 seconds. Neither timezone was in DST mode.
 
236
    tzinfo = pytz.timezone('Europe/Vilnius')
 
237
    instant = timedelta(seconds=31)
 
238
    transition_time = datetime(1916, 12, 31, 22, 36, 00, tzinfo=UTC)
 
239
    before = {
 
240
        'tzname': 'WMT',
 
241
        'utcoffset': timedelta(hours=1, minutes=24),
 
242
        'dst': timedelta(0),
 
243
        }
 
244
    after = {
 
245
        'tzname': 'KMT',
 
246
        'utcoffset': timedelta(hours=1, minutes=36), # Really 1:35:36
 
247
        'dst': timedelta(0),
 
248
        }
 
249
 
 
250
 
 
251
class ReferenceUSEasternDSTStartTestCase(USEasternDSTStartTestCase):
 
252
    tzinfo = reference.Eastern
 
253
    def test_arithmetic(self):
 
254
        # Reference implementation cannot handle this
 
255
        pass
 
256
 
 
257
 
 
258
class ReferenceUSEasternDSTEndTestCase(USEasternDSTEndTestCase):
 
259
    tzinfo = reference.Eastern
 
260
 
 
261
    def testHourBefore(self):
 
262
        # Python's datetime library has a bug, where the hour before
 
263
        # a daylight savings transition is one hour out. For example,
 
264
        # at the end of US/Eastern daylight savings time, 01:00 EST
 
265
        # occurs twice (once at 05:00 UTC and once at 06:00 UTC),
 
266
        # whereas the first should actually be 01:00 EDT.
 
267
        # Note that this bug is by design - by accepting this ambiguity
 
268
        # for one hour one hour per year, an is_dst flag on datetime.time
 
269
        # became unnecessary.
 
270
        self._test_all(
 
271
                self.transition_time - timedelta(hours=1), self.after
 
272
                )
 
273
 
 
274
    def testInstantBefore(self):
 
275
        self._test_all(
 
276
                self.transition_time - timedelta(seconds=1), self.after
 
277
                )
 
278
 
 
279
    def test_arithmetic(self):
 
280
        # Reference implementation cannot handle this
 
281
        pass
 
282
 
 
283
 
 
284
class LocalTestCase(unittest.TestCase):
 
285
    def testLocalize(self):
 
286
        loc_tz = pytz.timezone('Europe/Amsterdam')
 
287
 
 
288
        loc_time = loc_tz.localize(datetime(1930, 5, 10, 0, 0, 0))
 
289
        # Actually +00:19:32, but Python datetime rounds this
 
290
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'AMT+0020')
 
291
 
 
292
        loc_time = loc_tz.localize(datetime(1930, 5, 20, 0, 0, 0))
 
293
        # Actually +00:19:32, but Python datetime rounds this
 
294
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'NST+0120')
 
295
 
 
296
        loc_time = loc_tz.localize(datetime(1940, 5, 10, 0, 0, 0))
 
297
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'NET+0020')
 
298
 
 
299
        loc_time = loc_tz.localize(datetime(1940, 5, 20, 0, 0, 0))
 
300
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'CEST+0200')
 
301
 
 
302
        loc_time = loc_tz.localize(datetime(2004, 2, 1, 0, 0, 0))
 
303
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'CET+0100')
 
304
 
 
305
        loc_time = loc_tz.localize(datetime(2004, 4, 1, 0, 0, 0))
 
306
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'CEST+0200')
 
307
 
 
308
        tz = pytz.timezone('Europe/Amsterdam')
 
309
        loc_time = loc_tz.localize(datetime(1943, 3, 29, 1, 59, 59))
 
310
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'CET+0100')
 
311
 
 
312
 
 
313
        # Switch to US
 
314
        loc_tz = pytz.timezone('US/Eastern')
 
315
 
 
316
        # End of DST ambiguity check
 
317
        loc_time = loc_tz.localize(datetime(1918, 10, 27, 1, 59, 59), is_dst=1)
 
318
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'EDT-0400')
 
319
 
 
320
        loc_time = loc_tz.localize(datetime(1918, 10, 27, 1, 59, 59), is_dst=0)
 
321
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'EST-0500')
 
322
 
 
323
        self.failUnlessRaises(pytz.AmbiguousTimeError,
 
324
                loc_tz.localize, datetime(1918, 10, 27, 1, 59, 59), is_dst=None
 
325
                )
 
326
 
 
327
        # Weird changes - war time and peace time both is_dst==True
 
328
 
 
329
        loc_time = loc_tz.localize(datetime(1942, 2, 9, 3, 0, 0))
 
330
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'EWT-0400')
 
331
 
 
332
        loc_time = loc_tz.localize(datetime(1945, 8, 14, 19, 0, 0))
 
333
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'EPT-0400')
 
334
 
 
335
        loc_time = loc_tz.localize(datetime(1945, 9, 30, 1, 0, 0), is_dst=1)
 
336
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'EPT-0400')
 
337
 
 
338
        loc_time = loc_tz.localize(datetime(1945, 9, 30, 1, 0, 0), is_dst=0)
 
339
        self.failUnlessEqual(loc_time.strftime('%Z%z'), 'EST-0500')
 
340
 
 
341
    def testNormalize(self):
 
342
        tz = pytz.timezone('US/Eastern')
 
343
        dt = datetime(2004, 4, 4, 7, 0, 0, tzinfo=UTC).astimezone(tz)
 
344
        dt2 = dt - timedelta(minutes=10)
 
345
        self.failUnlessEqual(
 
346
                dt2.strftime('%Y-%m-%d %H:%M:%S %Z%z'),
 
347
                '2004-04-04 02:50:00 EDT-0400'
 
348
                )
 
349
 
 
350
        dt2 = tz.normalize(dt2)
 
351
        self.failUnlessEqual(
 
352
                dt2.strftime('%Y-%m-%d %H:%M:%S %Z%z'),
 
353
                '2004-04-04 01:50:00 EST-0500'
 
354
                )
 
355
 
 
356
    def testPartialMinuteOffsets(self):
 
357
        # utcoffset in Amsterdam was not a whole minute until 1937
 
358
        # However, we fudge this by rounding them, as the Python
 
359
        # datetime library 
 
360
        tz = pytz.timezone('Europe/Amsterdam')
 
361
        utc_dt = datetime(1914, 1, 1, 13, 40, 28, tzinfo=UTC) # correct
 
362
        utc_dt = utc_dt.replace(second=0) # But we need to fudge it
 
363
        loc_dt = utc_dt.astimezone(tz)
 
364
        self.failUnlessEqual(
 
365
                loc_dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'),
 
366
                '1914-01-01 14:00:00 AMT+0020'
 
367
                )
 
368
 
 
369
        # And get back...
 
370
        utc_dt = loc_dt.astimezone(UTC)
 
371
        self.failUnlessEqual(
 
372
                utc_dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'),
 
373
                '1914-01-01 13:40:00 UTC+0000'
 
374
                )
 
375
 
 
376
    def no_testCreateLocaltime(self):
 
377
        # It would be nice if this worked, but it doesn't.
 
378
        tz = pytz.timezone('Europe/Amsterdam')
 
379
        dt = datetime(2004, 10, 31, 2, 0, 0, tzinfo=tz)
 
380
        self.failUnlessEqual(
 
381
                dt.strftime(fmt),
 
382
                '2004-10-31 02:00:00 CET+0100'
 
383
                )
 
384
 
 
385
def test_suite():
 
386
    suite = unittest.TestSuite()
 
387
    suite.addTest(doctest.DocTestSuite('pytz'))
 
388
    suite.addTest(doctest.DocTestSuite('pytz.tzinfo'))
 
389
    suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(
 
390
        __import__('__main__')
 
391
        ))
 
392
    return suite
 
393
 
 
394
if __name__ == '__main__':
 
395
    suite = test_suite()
 
396
    if '-v' in sys.argv:
 
397
        runner = unittest.TextTestRunner(verbosity=2)
 
398
    else:
 
399
        runner = unittest.TextTestRunner()
 
400
    runner.run(suite)
 
401
 
 
402
# vim: set filetype=python ts=4 sw=4 et
 
403