Strengthen the tests for format '%Y', in relation with issue #13305.

This commit is contained in:
Florent Xicluna 2011-11-01 12:56:14 +01:00
parent b6dbc9ee15
commit 49ce06858b
2 changed files with 62 additions and 16 deletions

View File

@ -1291,8 +1291,16 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
def test_strftime_y2k(self): def test_strftime_y2k(self):
for y in (1, 49, 70, 99, 100, 999, 1000, 1970): for y in (1, 49, 70, 99, 100, 999, 1000, 1970):
self.assertIn(self.theclass(y, 1, 1).strftime("%Y"), d = self.theclass(y, 1, 1)
[str(y),'%04d' % y]) # Issue 13305: For years < 1000, the value is not always
# padded to 4 digits across platforms. The C standard
# assumes year >= 1900, so it does not specify the number
# of digits.
if d.strftime("%Y") != '%04d' % y:
# Year 42 returns '42', not padded
self.assertEqual(d.strftime("%Y"), '%d' % y)
# '0042' is obtained anyway
self.assertEqual(d.strftime("%4Y"), '%04d' % y)
def test_replace(self): def test_replace(self):
cls = self.theclass cls = self.theclass

View File

@ -70,28 +70,35 @@ class TimeTestCase(unittest.TestCase):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
time.strftime('%f') time.strftime('%f')
def _bounds_checking(self, func=time.strftime): def _bounds_checking(self, func):
# Make sure that strftime() checks the bounds of the various parts # Make sure that strftime() checks the bounds of the various parts
#of the time tuple (0 is valid for *all* values). # of the time tuple (0 is valid for *all* values).
# The year field is tested by other test cases above # The year field is tested by other test cases above
# Check month [1, 12] + zero support # Check month [1, 12] + zero support
func((1900, 0, 1, 0, 0, 0, 0, 1, -1))
func((1900, 12, 1, 0, 0, 0, 0, 1, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
(1900, -1, 1, 0, 0, 0, 0, 1, -1)) (1900, -1, 1, 0, 0, 0, 0, 1, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
(1900, 13, 1, 0, 0, 0, 0, 1, -1)) (1900, 13, 1, 0, 0, 0, 0, 1, -1))
# Check day of month [1, 31] + zero support # Check day of month [1, 31] + zero support
func((1900, 1, 0, 0, 0, 0, 0, 1, -1))
func((1900, 1, 31, 0, 0, 0, 0, 1, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
(1900, 1, -1, 0, 0, 0, 0, 1, -1)) (1900, 1, -1, 0, 0, 0, 0, 1, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
(1900, 1, 32, 0, 0, 0, 0, 1, -1)) (1900, 1, 32, 0, 0, 0, 0, 1, -1))
# Check hour [0, 23] # Check hour [0, 23]
func((1900, 1, 1, 0, 0, 0, 0, 1, -1))
func((1900, 1, 1, 23, 0, 0, 0, 1, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
(1900, 1, 1, -1, 0, 0, 0, 1, -1)) (1900, 1, 1, -1, 0, 0, 0, 1, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
(1900, 1, 1, 24, 0, 0, 0, 1, -1)) (1900, 1, 1, 24, 0, 0, 0, 1, -1))
# Check minute [0, 59] # Check minute [0, 59]
func((1900, 1, 1, 0, 59, 0, 0, 1, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
(1900, 1, 1, 0, -1, 0, 0, 1, -1)) (1900, 1, 1, 0, -1, 0, 0, 1, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
@ -101,15 +108,21 @@ class TimeTestCase(unittest.TestCase):
(1900, 1, 1, 0, 0, -1, 0, 1, -1)) (1900, 1, 1, 0, 0, -1, 0, 1, -1))
# C99 only requires allowing for one leap second, but Python's docs say # C99 only requires allowing for one leap second, but Python's docs say
# allow two leap seconds (0..61) # allow two leap seconds (0..61)
func((1900, 1, 1, 0, 0, 60, 0, 1, -1))
func((1900, 1, 1, 0, 0, 61, 0, 1, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
(1900, 1, 1, 0, 0, 62, 0, 1, -1)) (1900, 1, 1, 0, 0, 62, 0, 1, -1))
# No check for upper-bound day of week; # No check for upper-bound day of week;
# value forced into range by a ``% 7`` calculation. # value forced into range by a ``% 7`` calculation.
# Start check at -2 since gettmarg() increments value before taking # Start check at -2 since gettmarg() increments value before taking
# modulo. # modulo.
self.assertEqual(func((1900, 1, 1, 0, 0, 0, -1, 1, -1)),
func((1900, 1, 1, 0, 0, 0, +6, 1, -1)))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
(1900, 1, 1, 0, 0, 0, -2, 1, -1)) (1900, 1, 1, 0, 0, 0, -2, 1, -1))
# Check day of the year [1, 366] + zero support # Check day of the year [1, 366] + zero support
func((1900, 1, 1, 0, 0, 0, 0, 0, -1))
func((1900, 1, 1, 0, 0, 0, 0, 366, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
(1900, 1, 1, 0, 0, 0, 0, -1, -1)) (1900, 1, 1, 0, 0, 0, 0, -1, -1))
self.assertRaises(ValueError, func, self.assertRaises(ValueError, func,
@ -299,6 +312,8 @@ class _BaseYearTest(unittest.TestCase):
raise NotImplementedError() raise NotImplementedError()
class _TestAsctimeYear: class _TestAsctimeYear:
_format = '%d'
def yearstr(self, y): def yearstr(self, y):
return time.asctime((y,) + (0,) * 8).split()[-1] return time.asctime((y,) + (0,) * 8).split()[-1]
@ -308,8 +323,41 @@ class _TestAsctimeYear:
self.assertEqual(self.yearstr(123456789), '123456789') self.assertEqual(self.yearstr(123456789), '123456789')
class _TestStrftimeYear: class _TestStrftimeYear:
# Issue 13305: For years < 1000, the value is not always
# padded to 4 digits across platforms. The C standard
# assumes year >= 1900, so it does not specify the number
# of digits.
if time.strftime('%Y', (1,) + (0,) * 8) == '0001':
_format = '%04d'
else:
_format = '%d'
def yearstr(self, y): def yearstr(self, y):
return time.strftime('%Y', (y,) + (0,) * 8).split()[-1] return time.strftime('%Y', (y,) + (0,) * 8)
def test_4dyear(self):
# Check that we can return the zero padded value.
if self._format == '%04d':
self.test_year('%04d')
else:
def year4d(y):
return time.strftime('%4Y', (y,) + (0,) * 8)
self.test_year('%04d', func=year4d)
class _Test4dYear(_BaseYearTest):
_format = '%d'
def test_year(self, fmt=None, func=None):
fmt = fmt or self._format
func = func or self.yearstr
self.assertEqual(func(1), fmt % 1)
self.assertEqual(func(68), fmt % 68)
self.assertEqual(func(69), fmt % 69)
self.assertEqual(func(99), fmt % 99)
self.assertEqual(func(999), fmt % 999)
self.assertEqual(func(9999), fmt % 9999)
def test_large_year(self): def test_large_year(self):
# Check that it doesn't crash for year > 9999 # Check that it doesn't crash for year > 9999
@ -321,23 +369,13 @@ class _TestStrftimeYear:
self.assertEqual(text, '12345') self.assertEqual(text, '12345')
self.assertEqual(self.yearstr(123456789), '123456789') self.assertEqual(self.yearstr(123456789), '123456789')
class _Test4dYear(_BaseYearTest):
def test_year(self):
self.assertIn(self.yearstr(1), ('1', '0001'))
self.assertIn(self.yearstr(68), ('68', '0068'))
self.assertIn(self.yearstr(69), ('69', '0069'))
self.assertIn(self.yearstr(99), ('99', '0099'))
self.assertIn(self.yearstr(999), ('999', '0999'))
self.assertEqual(self.yearstr(9999), '9999')
def test_negative(self): def test_negative(self):
try: try:
text = self.yearstr(-1) text = self.yearstr(-1)
except ValueError: except ValueError:
# strftime() is limited to [1; 9999] with Visual Studio # strftime() is limited to [1; 9999] with Visual Studio
return return
self.assertIn(text, ('-1', '-001')) self.assertEqual(text, self._format % -1)
self.assertEqual(self.yearstr(-1234), '-1234') self.assertEqual(self.yearstr(-1234), '-1234')
self.assertEqual(self.yearstr(-123456), '-123456') self.assertEqual(self.yearstr(-123456), '-123456')