1from test import test_support
2import time
3import unittest
4import sys
5import sysconfig
6
7
8# Max year is only limited by the size of C int.
9SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4
10TIME_MAXYEAR = (1 << 8 * SIZEOF_INT - 1) - 1
11
12
13class TimeTestCase(unittest.TestCase):
14
15    def setUp(self):
16        self.t = time.time()
17
18    def test_data_attributes(self):
19        time.altzone
20        time.daylight
21        time.timezone
22        time.tzname
23
24    def test_clock(self):
25        time.clock()
26
27    def test_conversions(self):
28        self.assertTrue(time.ctime(self.t)
29                     == time.asctime(time.localtime(self.t)))
30        self.assertTrue(long(time.mktime(time.localtime(self.t)))
31                     == long(self.t))
32
33    def test_sleep(self):
34        time.sleep(1.2)
35
36    def test_strftime(self):
37        tt = time.gmtime(self.t)
38        for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I',
39                          'j', 'm', 'M', 'p', 'S',
40                          'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'):
41            format = ' %' + directive
42            try:
43                time.strftime(format, tt)
44            except ValueError:
45                self.fail('conversion specifier: %r failed.' % format)
46
47        # Issue #10762: Guard against invalid/non-supported format string
48        # so that Python don't crash (Windows crashes when the format string
49        # input to [w]strftime is not kosher.
50        if sys.platform.startswith('win'):
51            with self.assertRaises(ValueError):
52                time.strftime('%f')
53
54    def _bounds_checking(self, func):
55        # Make sure that strftime() checks the bounds of the various parts
56        # of the time tuple (0 is valid for *all* values).
57
58        # The year field is tested by other test cases above
59
60        # Check month [1, 12] + zero support
61        func((1900, 0, 1, 0, 0, 0, 0, 1, -1))
62        func((1900, 12, 1, 0, 0, 0, 0, 1, -1))
63        self.assertRaises(ValueError, func,
64                            (1900, -1, 1, 0, 0, 0, 0, 1, -1))
65        self.assertRaises(ValueError, func,
66                            (1900, 13, 1, 0, 0, 0, 0, 1, -1))
67        # Check day of month [1, 31] + zero support
68        func((1900, 1, 0, 0, 0, 0, 0, 1, -1))
69        func((1900, 1, 31, 0, 0, 0, 0, 1, -1))
70        self.assertRaises(ValueError, func,
71                            (1900, 1, -1, 0, 0, 0, 0, 1, -1))
72        self.assertRaises(ValueError, func,
73                            (1900, 1, 32, 0, 0, 0, 0, 1, -1))
74        # Check hour [0, 23]
75        func((1900, 1, 1, 23, 0, 0, 0, 1, -1))
76        self.assertRaises(ValueError, func,
77                            (1900, 1, 1, -1, 0, 0, 0, 1, -1))
78        self.assertRaises(ValueError, func,
79                            (1900, 1, 1, 24, 0, 0, 0, 1, -1))
80        # Check minute [0, 59]
81        func((1900, 1, 1, 0, 59, 0, 0, 1, -1))
82        self.assertRaises(ValueError, func,
83                            (1900, 1, 1, 0, -1, 0, 0, 1, -1))
84        self.assertRaises(ValueError, func,
85                            (1900, 1, 1, 0, 60, 0, 0, 1, -1))
86        # Check second [0, 61]
87        self.assertRaises(ValueError, func,
88                            (1900, 1, 1, 0, 0, -1, 0, 1, -1))
89        # C99 only requires allowing for one leap second, but Python's docs say
90        # allow two leap seconds (0..61)
91        func((1900, 1, 1, 0, 0, 60, 0, 1, -1))
92        func((1900, 1, 1, 0, 0, 61, 0, 1, -1))
93        self.assertRaises(ValueError, func,
94                            (1900, 1, 1, 0, 0, 62, 0, 1, -1))
95        # No check for upper-bound day of week;
96        #  value forced into range by a ``% 7`` calculation.
97        # Start check at -2 since gettmarg() increments value before taking
98        #  modulo.
99        self.assertEqual(func((1900, 1, 1, 0, 0, 0, -1, 1, -1)),
100                         func((1900, 1, 1, 0, 0, 0, +6, 1, -1)))
101        self.assertRaises(ValueError, func,
102                            (1900, 1, 1, 0, 0, 0, -2, 1, -1))
103        # Check day of the year [1, 366] + zero support
104        func((1900, 1, 1, 0, 0, 0, 0, 0, -1))
105        func((1900, 1, 1, 0, 0, 0, 0, 366, -1))
106        self.assertRaises(ValueError, func,
107                            (1900, 1, 1, 0, 0, 0, 0, -1, -1))
108        self.assertRaises(ValueError, func,
109                            (1900, 1, 1, 0, 0, 0, 0, 367, -1))
110
111    def test_strftime_bounding_check(self):
112        self._bounds_checking(lambda tup: time.strftime('', tup))
113
114    def test_strftime_bounds_checking(self):
115        # Make sure that strftime() checks the bounds of the various parts
116        #of the time tuple (0 is valid for *all* values).
117
118        # Check year [1900, max(int)]
119        self.assertRaises(ValueError, time.strftime, '',
120                            (1899, 1, 1, 0, 0, 0, 0, 1, -1))
121        if time.accept2dyear:
122            self.assertRaises(ValueError, time.strftime, '',
123                                (-1, 1, 1, 0, 0, 0, 0, 1, -1))
124            self.assertRaises(ValueError, time.strftime, '',
125                                (100, 1, 1, 0, 0, 0, 0, 1, -1))
126        # Check month [1, 12] + zero support
127        self.assertRaises(ValueError, time.strftime, '',
128                            (1900, -1, 1, 0, 0, 0, 0, 1, -1))
129        self.assertRaises(ValueError, time.strftime, '',
130                            (1900, 13, 1, 0, 0, 0, 0, 1, -1))
131        # Check day of month [1, 31] + zero support
132        self.assertRaises(ValueError, time.strftime, '',
133                            (1900, 1, -1, 0, 0, 0, 0, 1, -1))
134        self.assertRaises(ValueError, time.strftime, '',
135                            (1900, 1, 32, 0, 0, 0, 0, 1, -1))
136        # Check hour [0, 23]
137        self.assertRaises(ValueError, time.strftime, '',
138                            (1900, 1, 1, -1, 0, 0, 0, 1, -1))
139        self.assertRaises(ValueError, time.strftime, '',
140                            (1900, 1, 1, 24, 0, 0, 0, 1, -1))
141        # Check minute [0, 59]
142        self.assertRaises(ValueError, time.strftime, '',
143                            (1900, 1, 1, 0, -1, 0, 0, 1, -1))
144        self.assertRaises(ValueError, time.strftime, '',
145                            (1900, 1, 1, 0, 60, 0, 0, 1, -1))
146        # Check second [0, 61]
147        self.assertRaises(ValueError, time.strftime, '',
148                            (1900, 1, 1, 0, 0, -1, 0, 1, -1))
149        # C99 only requires allowing for one leap second, but Python's docs say
150        # allow two leap seconds (0..61)
151        self.assertRaises(ValueError, time.strftime, '',
152                            (1900, 1, 1, 0, 0, 62, 0, 1, -1))
153        # No check for upper-bound day of week;
154        #  value forced into range by a ``% 7`` calculation.
155        # Start check at -2 since gettmarg() increments value before taking
156        #  modulo.
157        self.assertRaises(ValueError, time.strftime, '',
158                            (1900, 1, 1, 0, 0, 0, -2, 1, -1))
159        # Check day of the year [1, 366] + zero support
160        self.assertRaises(ValueError, time.strftime, '',
161                            (1900, 1, 1, 0, 0, 0, 0, -1, -1))
162        self.assertRaises(ValueError, time.strftime, '',
163                            (1900, 1, 1, 0, 0, 0, 0, 367, -1))
164
165    def test_default_values_for_zero(self):
166        # Make sure that using all zeros uses the proper default values.
167        # No test for daylight savings since strftime() does not change output
168        # based on its value.
169        expected = "2000 01 01 00 00 00 1 001"
170        result = time.strftime("%Y %m %d %H %M %S %w %j", (0,)*9)
171        self.assertEqual(expected, result)
172
173    def test_strptime(self):
174        # Should be able to go round-trip from strftime to strptime without
175        # raising an exception.
176        tt = time.gmtime(self.t)
177        for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I',
178                          'j', 'm', 'M', 'p', 'S',
179                          'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'):
180            format = '%' + directive
181            strf_output = time.strftime(format, tt)
182            try:
183                time.strptime(strf_output, format)
184            except ValueError:
185                self.fail("conversion specifier %r failed with '%s' input." %
186                          (format, strf_output))
187
188    def test_asctime(self):
189        time.asctime(time.gmtime(self.t))
190        self.assertRaises(TypeError, time.asctime, 0)
191        self.assertRaises(TypeError, time.asctime, ())
192
193        # Max year is only limited by the size of C int.
194        asc = time.asctime((TIME_MAXYEAR, 6, 1) + (0,) * 6)
195        self.assertEqual(asc[-len(str(TIME_MAXYEAR)):], str(TIME_MAXYEAR))
196        self.assertRaises(OverflowError, time.asctime,
197                          (TIME_MAXYEAR + 1,) + (0,) * 8)
198        self.assertRaises(TypeError, time.asctime, 0)
199        self.assertRaises(TypeError, time.asctime, ())
200        self.assertRaises(TypeError, time.asctime, (0,) * 10)
201
202    @unittest.skipIf(not hasattr(time, "tzset"),
203        "time module has no attribute tzset")
204    def test_tzset(self):
205
206        from os import environ
207
208        # Epoch time of midnight Dec 25th 2002. Never DST in northern
209        # hemisphere.
210        xmas2002 = 1040774400.0
211
212        # These formats are correct for 2002, and possibly future years
213        # This format is the 'standard' as documented at:
214        # http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap08.html
215        # They are also documented in the tzset(3) man page on most Unix
216        # systems.
217        eastern = 'EST+05EDT,M4.1.0,M10.5.0'
218        victoria = 'AEST-10AEDT-11,M10.5.0,M3.5.0'
219        utc='UTC+0'
220
221        org_TZ = environ.get('TZ',None)
222        try:
223            # Make sure we can switch to UTC time and results are correct
224            # Note that unknown timezones default to UTC.
225            # Note that altzone is undefined in UTC, as there is no DST
226            environ['TZ'] = eastern
227            time.tzset()
228            environ['TZ'] = utc
229            time.tzset()
230            self.assertEqual(
231                time.gmtime(xmas2002), time.localtime(xmas2002)
232                )
233            self.assertEqual(time.daylight, 0)
234            self.assertEqual(time.timezone, 0)
235            self.assertEqual(time.localtime(xmas2002).tm_isdst, 0)
236
237            # Make sure we can switch to US/Eastern
238            environ['TZ'] = eastern
239            time.tzset()
240            self.assertNotEqual(time.gmtime(xmas2002), time.localtime(xmas2002))
241            self.assertEqual(time.tzname, ('EST', 'EDT'))
242            self.assertEqual(len(time.tzname), 2)
243            self.assertEqual(time.daylight, 1)
244            self.assertEqual(time.timezone, 18000)
245            self.assertEqual(time.altzone, 14400)
246            self.assertEqual(time.localtime(xmas2002).tm_isdst, 0)
247            self.assertEqual(len(time.tzname), 2)
248
249            # Now go to the southern hemisphere.
250            environ['TZ'] = victoria
251            time.tzset()
252            self.assertNotEqual(time.gmtime(xmas2002), time.localtime(xmas2002))
253
254            # Issue #11886: Australian Eastern Standard Time (UTC+10) is called
255            # "EST" (as Eastern Standard Time, UTC-5) instead of "AEST" on some
256            # operating systems (e.g. FreeBSD), which is wrong. See for example
257            # this bug: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=93810
258            self.assertIn(time.tzname[0], ('AEST' 'EST'), time.tzname[0])
259            self.assertTrue(time.tzname[1] == 'AEDT', str(time.tzname[1]))
260            self.assertEqual(len(time.tzname), 2)
261            self.assertEqual(time.daylight, 1)
262            self.assertEqual(time.timezone, -36000)
263            self.assertEqual(time.altzone, -39600)
264            self.assertEqual(time.localtime(xmas2002).tm_isdst, 1)
265
266        finally:
267            # Repair TZ environment variable in case any other tests
268            # rely on it.
269            if org_TZ is not None:
270                environ['TZ'] = org_TZ
271            elif environ.has_key('TZ'):
272                del environ['TZ']
273            time.tzset()
274
275    def test_insane_timestamps(self):
276        # It's possible that some platform maps time_t to double,
277        # and that this test will fail there.  This test should
278        # exempt such platforms (provided they return reasonable
279        # results!).
280        for func in time.ctime, time.gmtime, time.localtime:
281            for unreasonable in -1e200, 1e200:
282                self.assertRaises(ValueError, func, unreasonable)
283
284    def test_ctime_without_arg(self):
285        # Not sure how to check the values, since the clock could tick
286        # at any time.  Make sure these are at least accepted and
287        # don't raise errors.
288        time.ctime()
289        time.ctime(None)
290
291    def test_gmtime_without_arg(self):
292        gt0 = time.gmtime()
293        gt1 = time.gmtime(None)
294        t0 = time.mktime(gt0)
295        t1 = time.mktime(gt1)
296        self.assertTrue(0 <= (t1-t0) < 0.2)
297
298    def test_localtime_without_arg(self):
299        lt0 = time.localtime()
300        lt1 = time.localtime(None)
301        t0 = time.mktime(lt0)
302        t1 = time.mktime(lt1)
303        self.assertTrue(0 <= (t1-t0) < 0.2)
304
305    def test_mktime(self):
306        # Issue #1726687
307        for t in (-2, -1, 0, 1):
308            try:
309                tt = time.localtime(t)
310            except (OverflowError, ValueError):
311                pass
312            else:
313                self.assertEqual(time.mktime(tt), t)
314
315
316def test_main():
317    test_support.run_unittest(TimeTestCase)
318
319
320if __name__ == "__main__":
321    test_main()
322