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