1 | """PyUnit testing against strptime"""
|
---|
2 |
|
---|
3 | import unittest
|
---|
4 | import time
|
---|
5 | import locale
|
---|
6 | import re
|
---|
7 | import sys
|
---|
8 | from test import test_support
|
---|
9 | from datetime import date as datetime_date
|
---|
10 |
|
---|
11 | import _strptime
|
---|
12 |
|
---|
13 | class getlang_Tests(unittest.TestCase):
|
---|
14 | """Test _getlang"""
|
---|
15 | def test_basic(self):
|
---|
16 | self.assertEqual(_strptime._getlang(), locale.getlocale(locale.LC_TIME))
|
---|
17 |
|
---|
18 | class LocaleTime_Tests(unittest.TestCase):
|
---|
19 | """Tests for _strptime.LocaleTime.
|
---|
20 |
|
---|
21 | All values are lower-cased when stored in LocaleTime, so make sure to
|
---|
22 | compare values after running ``lower`` on them.
|
---|
23 |
|
---|
24 | """
|
---|
25 |
|
---|
26 | def setUp(self):
|
---|
27 | """Create time tuple based on current time."""
|
---|
28 | self.time_tuple = time.localtime()
|
---|
29 | self.LT_ins = _strptime.LocaleTime()
|
---|
30 |
|
---|
31 | def compare_against_time(self, testing, directive, tuple_position,
|
---|
32 | error_msg):
|
---|
33 | """Helper method that tests testing against directive based on the
|
---|
34 | tuple_position of time_tuple. Uses error_msg as error message.
|
---|
35 |
|
---|
36 | """
|
---|
37 | strftime_output = time.strftime(directive, self.time_tuple).lower()
|
---|
38 | comparison = testing[self.time_tuple[tuple_position]]
|
---|
39 | self.assertIn(strftime_output, testing,
|
---|
40 | "%s: not found in tuple" % error_msg)
|
---|
41 | self.assertEqual(comparison, strftime_output,
|
---|
42 | "%s: position within tuple incorrect; %s != %s" %
|
---|
43 | (error_msg, comparison, strftime_output))
|
---|
44 |
|
---|
45 | def test_weekday(self):
|
---|
46 | # Make sure that full and abbreviated weekday names are correct in
|
---|
47 | # both string and position with tuple
|
---|
48 | self.compare_against_time(self.LT_ins.f_weekday, '%A', 6,
|
---|
49 | "Testing of full weekday name failed")
|
---|
50 | self.compare_against_time(self.LT_ins.a_weekday, '%a', 6,
|
---|
51 | "Testing of abbreviated weekday name failed")
|
---|
52 |
|
---|
53 | def test_month(self):
|
---|
54 | # Test full and abbreviated month names; both string and position
|
---|
55 | # within the tuple
|
---|
56 | self.compare_against_time(self.LT_ins.f_month, '%B', 1,
|
---|
57 | "Testing against full month name failed")
|
---|
58 | self.compare_against_time(self.LT_ins.a_month, '%b', 1,
|
---|
59 | "Testing against abbreviated month name failed")
|
---|
60 |
|
---|
61 | def test_am_pm(self):
|
---|
62 | # Make sure AM/PM representation done properly
|
---|
63 | strftime_output = time.strftime("%p", self.time_tuple).lower()
|
---|
64 | self.assertIn(strftime_output, self.LT_ins.am_pm,
|
---|
65 | "AM/PM representation not in tuple")
|
---|
66 | if self.time_tuple[3] < 12: position = 0
|
---|
67 | else: position = 1
|
---|
68 | self.assertEqual(self.LT_ins.am_pm[position], strftime_output,
|
---|
69 | "AM/PM representation in the wrong position within the tuple")
|
---|
70 |
|
---|
71 | def test_timezone(self):
|
---|
72 | # Make sure timezone is correct
|
---|
73 | timezone = time.strftime("%Z", self.time_tuple).lower()
|
---|
74 | if timezone:
|
---|
75 | self.assertTrue(timezone in self.LT_ins.timezone[0] or
|
---|
76 | timezone in self.LT_ins.timezone[1],
|
---|
77 | "timezone %s not found in %s" %
|
---|
78 | (timezone, self.LT_ins.timezone))
|
---|
79 |
|
---|
80 | def test_date_time(self):
|
---|
81 | # Check that LC_date_time, LC_date, and LC_time are correct
|
---|
82 | # the magic date is used so as to not have issues with %c when day of
|
---|
83 | # the month is a single digit and has a leading space. This is not an
|
---|
84 | # issue since strptime still parses it correctly. The problem is
|
---|
85 | # testing these directives for correctness by comparing strftime
|
---|
86 | # output.
|
---|
87 | magic_date = (1999, 3, 17, 22, 44, 55, 2, 76, 0)
|
---|
88 | strftime_output = time.strftime("%c", magic_date)
|
---|
89 | self.assertEqual(time.strftime(self.LT_ins.LC_date_time, magic_date),
|
---|
90 | strftime_output, "LC_date_time incorrect")
|
---|
91 | strftime_output = time.strftime("%x", magic_date)
|
---|
92 | self.assertEqual(time.strftime(self.LT_ins.LC_date, magic_date),
|
---|
93 | strftime_output, "LC_date incorrect")
|
---|
94 | strftime_output = time.strftime("%X", magic_date)
|
---|
95 | self.assertEqual(time.strftime(self.LT_ins.LC_time, magic_date),
|
---|
96 | strftime_output, "LC_time incorrect")
|
---|
97 | LT = _strptime.LocaleTime()
|
---|
98 | LT.am_pm = ('', '')
|
---|
99 | self.assertTrue(LT.LC_time, "LocaleTime's LC directives cannot handle "
|
---|
100 | "empty strings")
|
---|
101 |
|
---|
102 | def test_lang(self):
|
---|
103 | # Make sure lang is set to what _getlang() returns
|
---|
104 | # Assuming locale has not changed between now and when self.LT_ins was created
|
---|
105 | self.assertEqual(self.LT_ins.lang, _strptime._getlang())
|
---|
106 |
|
---|
107 |
|
---|
108 | class TimeRETests(unittest.TestCase):
|
---|
109 | """Tests for TimeRE."""
|
---|
110 |
|
---|
111 | def setUp(self):
|
---|
112 | """Construct generic TimeRE object."""
|
---|
113 | self.time_re = _strptime.TimeRE()
|
---|
114 | self.locale_time = _strptime.LocaleTime()
|
---|
115 |
|
---|
116 | def test_pattern(self):
|
---|
117 | # Test TimeRE.pattern
|
---|
118 | pattern_string = self.time_re.pattern(r"%a %A %d")
|
---|
119 | self.assertTrue(pattern_string.find(self.locale_time.a_weekday[2]) != -1,
|
---|
120 | "did not find abbreviated weekday in pattern string '%s'" %
|
---|
121 | pattern_string)
|
---|
122 | self.assertTrue(pattern_string.find(self.locale_time.f_weekday[4]) != -1,
|
---|
123 | "did not find full weekday in pattern string '%s'" %
|
---|
124 | pattern_string)
|
---|
125 | self.assertTrue(pattern_string.find(self.time_re['d']) != -1,
|
---|
126 | "did not find 'd' directive pattern string '%s'" %
|
---|
127 | pattern_string)
|
---|
128 |
|
---|
129 | def test_pattern_escaping(self):
|
---|
130 | # Make sure any characters in the format string that might be taken as
|
---|
131 | # regex syntax is escaped.
|
---|
132 | pattern_string = self.time_re.pattern("\d+")
|
---|
133 | self.assertIn(r"\\d\+", pattern_string,
|
---|
134 | "%s does not have re characters escaped properly" %
|
---|
135 | pattern_string)
|
---|
136 |
|
---|
137 | def test_compile(self):
|
---|
138 | # Check that compiled regex is correct
|
---|
139 | found = self.time_re.compile(r"%A").match(self.locale_time.f_weekday[6])
|
---|
140 | self.assertTrue(found and found.group('A') == self.locale_time.f_weekday[6],
|
---|
141 | "re object for '%A' failed")
|
---|
142 | compiled = self.time_re.compile(r"%a %b")
|
---|
143 | found = compiled.match("%s %s" % (self.locale_time.a_weekday[4],
|
---|
144 | self.locale_time.a_month[4]))
|
---|
145 | self.assertTrue(found,
|
---|
146 | "Match failed with '%s' regex and '%s' string" %
|
---|
147 | (compiled.pattern, "%s %s" % (self.locale_time.a_weekday[4],
|
---|
148 | self.locale_time.a_month[4])))
|
---|
149 | self.assertTrue(found.group('a') == self.locale_time.a_weekday[4] and
|
---|
150 | found.group('b') == self.locale_time.a_month[4],
|
---|
151 | "re object couldn't find the abbreviated weekday month in "
|
---|
152 | "'%s' using '%s'; group 'a' = '%s', group 'b' = %s'" %
|
---|
153 | (found.string, found.re.pattern, found.group('a'),
|
---|
154 | found.group('b')))
|
---|
155 | for directive in ('a','A','b','B','c','d','H','I','j','m','M','p','S',
|
---|
156 | 'U','w','W','x','X','y','Y','Z','%'):
|
---|
157 | compiled = self.time_re.compile("%" + directive)
|
---|
158 | found = compiled.match(time.strftime("%" + directive))
|
---|
159 | self.assertTrue(found, "Matching failed on '%s' using '%s' regex" %
|
---|
160 | (time.strftime("%" + directive),
|
---|
161 | compiled.pattern))
|
---|
162 |
|
---|
163 | def test_blankpattern(self):
|
---|
164 | # Make sure when tuple or something has no values no regex is generated.
|
---|
165 | # Fixes bug #661354
|
---|
166 | test_locale = _strptime.LocaleTime()
|
---|
167 | test_locale.timezone = (frozenset(), frozenset())
|
---|
168 | self.assertEqual(_strptime.TimeRE(test_locale).pattern("%Z"), '',
|
---|
169 | "with timezone == ('',''), TimeRE().pattern('%Z') != ''")
|
---|
170 |
|
---|
171 | def test_matching_with_escapes(self):
|
---|
172 | # Make sure a format that requires escaping of characters works
|
---|
173 | compiled_re = self.time_re.compile("\w+ %m")
|
---|
174 | found = compiled_re.match("\w+ 10")
|
---|
175 | self.assertTrue(found, "Escaping failed of format '\w+ 10'")
|
---|
176 |
|
---|
177 | def test_locale_data_w_regex_metacharacters(self):
|
---|
178 | # Check that if locale data contains regex metacharacters they are
|
---|
179 | # escaped properly.
|
---|
180 | # Discovered by bug #1039270 .
|
---|
181 | locale_time = _strptime.LocaleTime()
|
---|
182 | locale_time.timezone = (frozenset(("utc", "gmt",
|
---|
183 | "Tokyo (standard time)")),
|
---|
184 | frozenset("Tokyo (daylight time)"))
|
---|
185 | time_re = _strptime.TimeRE(locale_time)
|
---|
186 | self.assertTrue(time_re.compile("%Z").match("Tokyo (standard time)"),
|
---|
187 | "locale data that contains regex metacharacters is not"
|
---|
188 | " properly escaped")
|
---|
189 |
|
---|
190 | def test_whitespace_substitution(self):
|
---|
191 | # When pattern contains whitespace, make sure it is taken into account
|
---|
192 | # so as to not allow to subpatterns to end up next to each other and
|
---|
193 | # "steal" characters from each other.
|
---|
194 | pattern = self.time_re.pattern('%j %H')
|
---|
195 | self.assertFalse(re.match(pattern, "180"))
|
---|
196 | self.assertTrue(re.match(pattern, "18 0"))
|
---|
197 |
|
---|
198 |
|
---|
199 | class StrptimeTests(unittest.TestCase):
|
---|
200 | """Tests for _strptime.strptime."""
|
---|
201 |
|
---|
202 | def setUp(self):
|
---|
203 | """Create testing time tuple."""
|
---|
204 | self.time_tuple = time.gmtime()
|
---|
205 |
|
---|
206 | def test_ValueError(self):
|
---|
207 | # Make sure ValueError is raised when match fails or format is bad
|
---|
208 | self.assertRaises(ValueError, _strptime._strptime_time, data_string="%d",
|
---|
209 | format="%A")
|
---|
210 | for bad_format in ("%", "% ", "%e"):
|
---|
211 | try:
|
---|
212 | _strptime._strptime_time("2005", bad_format)
|
---|
213 | except ValueError:
|
---|
214 | continue
|
---|
215 | except Exception, err:
|
---|
216 | self.fail("'%s' raised %s, not ValueError" %
|
---|
217 | (bad_format, err.__class__.__name__))
|
---|
218 | else:
|
---|
219 | self.fail("'%s' did not raise ValueError" % bad_format)
|
---|
220 |
|
---|
221 | def test_unconverteddata(self):
|
---|
222 | # Check ValueError is raised when there is unconverted data
|
---|
223 | self.assertRaises(ValueError, _strptime._strptime_time, "10 12", "%m")
|
---|
224 |
|
---|
225 | def helper(self, directive, position):
|
---|
226 | """Helper fxn in testing."""
|
---|
227 | strf_output = time.strftime("%" + directive, self.time_tuple)
|
---|
228 | strp_output = _strptime._strptime_time(strf_output, "%" + directive)
|
---|
229 | self.assertTrue(strp_output[position] == self.time_tuple[position],
|
---|
230 | "testing of '%s' directive failed; '%s' -> %s != %s" %
|
---|
231 | (directive, strf_output, strp_output[position],
|
---|
232 | self.time_tuple[position]))
|
---|
233 |
|
---|
234 | def test_year(self):
|
---|
235 | # Test that the year is handled properly
|
---|
236 | for directive in ('y', 'Y'):
|
---|
237 | self.helper(directive, 0)
|
---|
238 | # Must also make sure %y values are correct for bounds set by Open Group
|
---|
239 | for century, bounds in ((1900, ('69', '99')), (2000, ('00', '68'))):
|
---|
240 | for bound in bounds:
|
---|
241 | strp_output = _strptime._strptime_time(bound, '%y')
|
---|
242 | expected_result = century + int(bound)
|
---|
243 | self.assertTrue(strp_output[0] == expected_result,
|
---|
244 | "'y' test failed; passed in '%s' "
|
---|
245 | "and returned '%s'" % (bound, strp_output[0]))
|
---|
246 |
|
---|
247 | def test_month(self):
|
---|
248 | # Test for month directives
|
---|
249 | for directive in ('B', 'b', 'm'):
|
---|
250 | self.helper(directive, 1)
|
---|
251 |
|
---|
252 | def test_day(self):
|
---|
253 | # Test for day directives
|
---|
254 | self.helper('d', 2)
|
---|
255 |
|
---|
256 | def test_hour(self):
|
---|
257 | # Test hour directives
|
---|
258 | self.helper('H', 3)
|
---|
259 | strf_output = time.strftime("%I %p", self.time_tuple)
|
---|
260 | strp_output = _strptime._strptime_time(strf_output, "%I %p")
|
---|
261 | self.assertTrue(strp_output[3] == self.time_tuple[3],
|
---|
262 | "testing of '%%I %%p' directive failed; '%s' -> %s != %s" %
|
---|
263 | (strf_output, strp_output[3], self.time_tuple[3]))
|
---|
264 |
|
---|
265 | def test_minute(self):
|
---|
266 | # Test minute directives
|
---|
267 | self.helper('M', 4)
|
---|
268 |
|
---|
269 | def test_second(self):
|
---|
270 | # Test second directives
|
---|
271 | self.helper('S', 5)
|
---|
272 |
|
---|
273 | def test_fraction(self):
|
---|
274 | # Test microseconds
|
---|
275 | import datetime
|
---|
276 | d = datetime.datetime(2012, 12, 20, 12, 34, 56, 78987)
|
---|
277 | tup, frac = _strptime._strptime(str(d), format="%Y-%m-%d %H:%M:%S.%f")
|
---|
278 | self.assertEqual(frac, d.microsecond)
|
---|
279 |
|
---|
280 | def test_weekday(self):
|
---|
281 | # Test weekday directives
|
---|
282 | for directive in ('A', 'a', 'w'):
|
---|
283 | self.helper(directive,6)
|
---|
284 |
|
---|
285 | def test_julian(self):
|
---|
286 | # Test julian directives
|
---|
287 | self.helper('j', 7)
|
---|
288 |
|
---|
289 | def test_timezone(self):
|
---|
290 | # Test timezone directives.
|
---|
291 | # When gmtime() is used with %Z, entire result of strftime() is empty.
|
---|
292 | # Check for equal timezone names deals with bad locale info when this
|
---|
293 | # occurs; first found in FreeBSD 4.4.
|
---|
294 | strp_output = _strptime._strptime_time("UTC", "%Z")
|
---|
295 | self.assertEqual(strp_output.tm_isdst, 0)
|
---|
296 | strp_output = _strptime._strptime_time("GMT", "%Z")
|
---|
297 | self.assertEqual(strp_output.tm_isdst, 0)
|
---|
298 | time_tuple = time.localtime()
|
---|
299 | strf_output = time.strftime("%Z") #UTC does not have a timezone
|
---|
300 | strp_output = _strptime._strptime_time(strf_output, "%Z")
|
---|
301 | locale_time = _strptime.LocaleTime()
|
---|
302 | if time.tzname[0] != time.tzname[1] or not time.daylight:
|
---|
303 | self.assertTrue(strp_output[8] == time_tuple[8],
|
---|
304 | "timezone check failed; '%s' -> %s != %s" %
|
---|
305 | (strf_output, strp_output[8], time_tuple[8]))
|
---|
306 | else:
|
---|
307 | self.assertTrue(strp_output[8] == -1,
|
---|
308 | "LocaleTime().timezone has duplicate values and "
|
---|
309 | "time.daylight but timezone value not set to -1")
|
---|
310 |
|
---|
311 | def test_bad_timezone(self):
|
---|
312 | # Explicitly test possibility of bad timezone;
|
---|
313 | # when time.tzname[0] == time.tzname[1] and time.daylight
|
---|
314 | tz_name = time.tzname[0]
|
---|
315 | if tz_name.upper() in ("UTC", "GMT"):
|
---|
316 | return
|
---|
317 | try:
|
---|
318 | original_tzname = time.tzname
|
---|
319 | original_daylight = time.daylight
|
---|
320 | time.tzname = (tz_name, tz_name)
|
---|
321 | time.daylight = 1
|
---|
322 | tz_value = _strptime._strptime_time(tz_name, "%Z")[8]
|
---|
323 | self.assertEqual(tz_value, -1,
|
---|
324 | "%s lead to a timezone value of %s instead of -1 when "
|
---|
325 | "time.daylight set to %s and passing in %s" %
|
---|
326 | (time.tzname, tz_value, time.daylight, tz_name))
|
---|
327 | finally:
|
---|
328 | time.tzname = original_tzname
|
---|
329 | time.daylight = original_daylight
|
---|
330 |
|
---|
331 | def test_date_time(self):
|
---|
332 | # Test %c directive
|
---|
333 | for position in range(6):
|
---|
334 | self.helper('c', position)
|
---|
335 |
|
---|
336 | def test_date(self):
|
---|
337 | # Test %x directive
|
---|
338 | for position in range(0,3):
|
---|
339 | self.helper('x', position)
|
---|
340 |
|
---|
341 | def test_time(self):
|
---|
342 | # Test %X directive
|
---|
343 | for position in range(3,6):
|
---|
344 | self.helper('X', position)
|
---|
345 |
|
---|
346 | def test_percent(self):
|
---|
347 | # Make sure % signs are handled properly
|
---|
348 | strf_output = time.strftime("%m %% %Y", self.time_tuple)
|
---|
349 | strp_output = _strptime._strptime_time(strf_output, "%m %% %Y")
|
---|
350 | self.assertTrue(strp_output[0] == self.time_tuple[0] and
|
---|
351 | strp_output[1] == self.time_tuple[1],
|
---|
352 | "handling of percent sign failed")
|
---|
353 |
|
---|
354 | def test_caseinsensitive(self):
|
---|
355 | # Should handle names case-insensitively.
|
---|
356 | strf_output = time.strftime("%B", self.time_tuple)
|
---|
357 | self.assertTrue(_strptime._strptime_time(strf_output.upper(), "%B"),
|
---|
358 | "strptime does not handle ALL-CAPS names properly")
|
---|
359 | self.assertTrue(_strptime._strptime_time(strf_output.lower(), "%B"),
|
---|
360 | "strptime does not handle lowercase names properly")
|
---|
361 | self.assertTrue(_strptime._strptime_time(strf_output.capitalize(), "%B"),
|
---|
362 | "strptime does not handle capword names properly")
|
---|
363 |
|
---|
364 | def test_defaults(self):
|
---|
365 | # Default return value should be (1900, 1, 1, 0, 0, 0, 0, 1, 0)
|
---|
366 | defaults = (1900, 1, 1, 0, 0, 0, 0, 1, -1)
|
---|
367 | strp_output = _strptime._strptime_time('1', '%m')
|
---|
368 | self.assertTrue(strp_output == defaults,
|
---|
369 | "Default values for strptime() are incorrect;"
|
---|
370 | " %s != %s" % (strp_output, defaults))
|
---|
371 |
|
---|
372 | def test_escaping(self):
|
---|
373 | # Make sure all characters that have regex significance are escaped.
|
---|
374 | # Parentheses are in a purposeful order; will cause an error of
|
---|
375 | # unbalanced parentheses when the regex is compiled if they are not
|
---|
376 | # escaped.
|
---|
377 | # Test instigated by bug #796149 .
|
---|
378 | need_escaping = ".^$*+?{}\[]|)("
|
---|
379 | self.assertTrue(_strptime._strptime_time(need_escaping, need_escaping))
|
---|
380 |
|
---|
381 | def test_feb29_on_leap_year_without_year(self):
|
---|
382 | time.strptime("Feb 29", "%b %d")
|
---|
383 |
|
---|
384 | def test_mar1_comes_after_feb29_even_when_omitting_the_year(self):
|
---|
385 | self.assertLess(
|
---|
386 | time.strptime("Feb 29", "%b %d"),
|
---|
387 | time.strptime("Mar 1", "%b %d"))
|
---|
388 |
|
---|
389 | class Strptime12AMPMTests(unittest.TestCase):
|
---|
390 | """Test a _strptime regression in '%I %p' at 12 noon (12 PM)"""
|
---|
391 |
|
---|
392 | def test_twelve_noon_midnight(self):
|
---|
393 | eq = self.assertEqual
|
---|
394 | eq(time.strptime('12 PM', '%I %p')[3], 12)
|
---|
395 | eq(time.strptime('12 AM', '%I %p')[3], 0)
|
---|
396 | eq(_strptime._strptime_time('12 PM', '%I %p')[3], 12)
|
---|
397 | eq(_strptime._strptime_time('12 AM', '%I %p')[3], 0)
|
---|
398 |
|
---|
399 |
|
---|
400 | class JulianTests(unittest.TestCase):
|
---|
401 | """Test a _strptime regression that all julian (1-366) are accepted"""
|
---|
402 |
|
---|
403 | def test_all_julian_days(self):
|
---|
404 | eq = self.assertEqual
|
---|
405 | for i in range(1, 367):
|
---|
406 | # use 2004, since it is a leap year, we have 366 days
|
---|
407 | eq(_strptime._strptime_time('%d 2004' % i, '%j %Y')[7], i)
|
---|
408 |
|
---|
409 | class CalculationTests(unittest.TestCase):
|
---|
410 | """Test that strptime() fills in missing info correctly"""
|
---|
411 |
|
---|
412 | def setUp(self):
|
---|
413 | self.time_tuple = time.gmtime()
|
---|
414 |
|
---|
415 | def test_julian_calculation(self):
|
---|
416 | # Make sure that when Julian is missing that it is calculated
|
---|
417 | format_string = "%Y %m %d %H %M %S %w %Z"
|
---|
418 | result = _strptime._strptime_time(time.strftime(format_string, self.time_tuple),
|
---|
419 | format_string)
|
---|
420 | self.assertTrue(result.tm_yday == self.time_tuple.tm_yday,
|
---|
421 | "Calculation of tm_yday failed; %s != %s" %
|
---|
422 | (result.tm_yday, self.time_tuple.tm_yday))
|
---|
423 |
|
---|
424 | def test_gregorian_calculation(self):
|
---|
425 | # Test that Gregorian date can be calculated from Julian day
|
---|
426 | format_string = "%Y %H %M %S %w %j %Z"
|
---|
427 | result = _strptime._strptime_time(time.strftime(format_string, self.time_tuple),
|
---|
428 | format_string)
|
---|
429 | self.assertTrue(result.tm_year == self.time_tuple.tm_year and
|
---|
430 | result.tm_mon == self.time_tuple.tm_mon and
|
---|
431 | result.tm_mday == self.time_tuple.tm_mday,
|
---|
432 | "Calculation of Gregorian date failed;"
|
---|
433 | "%s-%s-%s != %s-%s-%s" %
|
---|
434 | (result.tm_year, result.tm_mon, result.tm_mday,
|
---|
435 | self.time_tuple.tm_year, self.time_tuple.tm_mon,
|
---|
436 | self.time_tuple.tm_mday))
|
---|
437 |
|
---|
438 | def test_day_of_week_calculation(self):
|
---|
439 | # Test that the day of the week is calculated as needed
|
---|
440 | format_string = "%Y %m %d %H %S %j %Z"
|
---|
441 | result = _strptime._strptime_time(time.strftime(format_string, self.time_tuple),
|
---|
442 | format_string)
|
---|
443 | self.assertTrue(result.tm_wday == self.time_tuple.tm_wday,
|
---|
444 | "Calculation of day of the week failed;"
|
---|
445 | "%s != %s" % (result.tm_wday, self.time_tuple.tm_wday))
|
---|
446 |
|
---|
447 | def test_week_of_year_and_day_of_week_calculation(self):
|
---|
448 | # Should be able to infer date if given year, week of year (%U or %W)
|
---|
449 | # and day of the week
|
---|
450 | def test_helper(ymd_tuple, test_reason):
|
---|
451 | for directive in ('W', 'U'):
|
---|
452 | format_string = "%%Y %%%s %%w" % directive
|
---|
453 | dt_date = datetime_date(*ymd_tuple)
|
---|
454 | strp_input = dt_date.strftime(format_string)
|
---|
455 | strp_output = _strptime._strptime_time(strp_input, format_string)
|
---|
456 | self.assertTrue(strp_output[:3] == ymd_tuple,
|
---|
457 | "%s(%s) test failed w/ '%s': %s != %s (%s != %s)" %
|
---|
458 | (test_reason, directive, strp_input,
|
---|
459 | strp_output[:3], ymd_tuple,
|
---|
460 | strp_output[7], dt_date.timetuple()[7]))
|
---|
461 | test_helper((1901, 1, 3), "week 0")
|
---|
462 | test_helper((1901, 1, 8), "common case")
|
---|
463 | test_helper((1901, 1, 13), "day on Sunday")
|
---|
464 | test_helper((1901, 1, 14), "day on Monday")
|
---|
465 | test_helper((1905, 1, 1), "Jan 1 on Sunday")
|
---|
466 | test_helper((1906, 1, 1), "Jan 1 on Monday")
|
---|
467 | test_helper((1906, 1, 7), "first Sunday in a year starting on Monday")
|
---|
468 | test_helper((1905, 12, 31), "Dec 31 on Sunday")
|
---|
469 | test_helper((1906, 12, 31), "Dec 31 on Monday")
|
---|
470 | test_helper((2008, 12, 29), "Monday in the last week of the year")
|
---|
471 | test_helper((2008, 12, 22), "Monday in the second-to-last week of the "
|
---|
472 | "year")
|
---|
473 | test_helper((1978, 10, 23), "randomly chosen date")
|
---|
474 | test_helper((2004, 12, 18), "randomly chosen date")
|
---|
475 | test_helper((1978, 10, 23), "year starting and ending on Monday while "
|
---|
476 | "date not on Sunday or Monday")
|
---|
477 | test_helper((1917, 12, 17), "year starting and ending on Monday with "
|
---|
478 | "a Monday not at the beginning or end "
|
---|
479 | "of the year")
|
---|
480 | test_helper((1917, 12, 31), "Dec 31 on Monday with year starting and "
|
---|
481 | "ending on Monday")
|
---|
482 | test_helper((2007, 01, 07), "First Sunday of 2007")
|
---|
483 | test_helper((2007, 01, 14), "Second Sunday of 2007")
|
---|
484 | test_helper((2006, 12, 31), "Last Sunday of 2006")
|
---|
485 | test_helper((2006, 12, 24), "Second to last Sunday of 2006")
|
---|
486 |
|
---|
487 |
|
---|
488 | class CacheTests(unittest.TestCase):
|
---|
489 | """Test that caching works properly."""
|
---|
490 |
|
---|
491 | def test_time_re_recreation(self):
|
---|
492 | # Make sure cache is recreated when current locale does not match what
|
---|
493 | # cached object was created with.
|
---|
494 | _strptime._strptime_time("10", "%d")
|
---|
495 | _strptime._strptime_time("2005", "%Y")
|
---|
496 | _strptime._TimeRE_cache.locale_time.lang = "Ni"
|
---|
497 | original_time_re = _strptime._TimeRE_cache
|
---|
498 | _strptime._strptime_time("10", "%d")
|
---|
499 | self.assertIsNot(original_time_re, _strptime._TimeRE_cache)
|
---|
500 | self.assertEqual(len(_strptime._regex_cache), 1)
|
---|
501 |
|
---|
502 | def test_regex_cleanup(self):
|
---|
503 | # Make sure cached regexes are discarded when cache becomes "full".
|
---|
504 | try:
|
---|
505 | del _strptime._regex_cache['%d']
|
---|
506 | except KeyError:
|
---|
507 | pass
|
---|
508 | bogus_key = 0
|
---|
509 | while len(_strptime._regex_cache) <= _strptime._CACHE_MAX_SIZE:
|
---|
510 | _strptime._regex_cache[bogus_key] = None
|
---|
511 | bogus_key += 1
|
---|
512 | _strptime._strptime_time("10", "%d")
|
---|
513 | self.assertEqual(len(_strptime._regex_cache), 1)
|
---|
514 |
|
---|
515 | def test_new_localetime(self):
|
---|
516 | # A new LocaleTime instance should be created when a new TimeRE object
|
---|
517 | # is created.
|
---|
518 | locale_time_id = _strptime._TimeRE_cache.locale_time
|
---|
519 | _strptime._TimeRE_cache.locale_time.lang = "Ni"
|
---|
520 | _strptime._strptime_time("10", "%d")
|
---|
521 | self.assertIsNot(locale_time_id, _strptime._TimeRE_cache.locale_time)
|
---|
522 |
|
---|
523 | def test_TimeRE_recreation(self):
|
---|
524 | # The TimeRE instance should be recreated upon changing the locale.
|
---|
525 | locale_info = locale.getlocale(locale.LC_TIME)
|
---|
526 | try:
|
---|
527 | locale.setlocale(locale.LC_TIME, ('en_US', 'UTF8'))
|
---|
528 | except locale.Error:
|
---|
529 | return
|
---|
530 | try:
|
---|
531 | _strptime._strptime_time('10', '%d')
|
---|
532 | # Get id of current cache object.
|
---|
533 | first_time_re = _strptime._TimeRE_cache
|
---|
534 | try:
|
---|
535 | # Change the locale and force a recreation of the cache.
|
---|
536 | locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8'))
|
---|
537 | _strptime._strptime_time('10', '%d')
|
---|
538 | # Get the new cache object's id.
|
---|
539 | second_time_re = _strptime._TimeRE_cache
|
---|
540 | # They should not be equal.
|
---|
541 | self.assertIsNot(first_time_re, second_time_re)
|
---|
542 | # Possible test locale is not supported while initial locale is.
|
---|
543 | # If this is the case just suppress the exception and fall-through
|
---|
544 | # to the resetting to the original locale.
|
---|
545 | except locale.Error:
|
---|
546 | pass
|
---|
547 | # Make sure we don't trample on the locale setting once we leave the
|
---|
548 | # test.
|
---|
549 | finally:
|
---|
550 | locale.setlocale(locale.LC_TIME, locale_info)
|
---|
551 |
|
---|
552 |
|
---|
553 | def test_main():
|
---|
554 | test_support.run_unittest(
|
---|
555 | getlang_Tests,
|
---|
556 | LocaleTime_Tests,
|
---|
557 | TimeRETests,
|
---|
558 | StrptimeTests,
|
---|
559 | Strptime12AMPMTests,
|
---|
560 | JulianTests,
|
---|
561 | CalculationTests,
|
---|
562 | CacheTests
|
---|
563 | )
|
---|
564 |
|
---|
565 |
|
---|
566 | if __name__ == '__main__':
|
---|
567 | test_main()
|
---|