From 49ce06858b51ef98c31431436b28d32dd3bd99cd Mon Sep 17 00:00:00 2001
From: Florent Xicluna <florent.xicluna@gmail.com>
Date: Tue, 1 Nov 2011 12:56:14 +0100
Subject: Strengthen the tests for format '%Y', in relation with issue #13305.

---
 Lib/test/datetimetester.py | 12 +++++++--
 Lib/test/test_time.py      | 66 ++++++++++++++++++++++++++++++++++++----------
 2 files changed, 62 insertions(+), 16 deletions(-)

diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index f91e8fc..85036aa 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -1291,8 +1291,16 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
 
     def test_strftime_y2k(self):
         for y in (1, 49, 70, 99, 100, 999, 1000, 1970):
-            self.assertIn(self.theclass(y, 1, 1).strftime("%Y"),
-                          [str(y),'%04d' % y])
+            d = self.theclass(y, 1, 1)
+            # 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):
         cls = self.theclass
diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
index 73c53b3..9e2e68d 100644
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -70,28 +70,35 @@ class TimeTestCase(unittest.TestCase):
             with self.assertRaises(ValueError):
                 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
-        #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
 
         # 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,
                             (1900, -1, 1, 0, 0, 0, 0, 1, -1))
         self.assertRaises(ValueError, func,
                             (1900, 13, 1, 0, 0, 0, 0, 1, -1))
         # 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,
                             (1900, 1, -1, 0, 0, 0, 0, 1, -1))
         self.assertRaises(ValueError, func,
                             (1900, 1, 32, 0, 0, 0, 0, 1, -1))
         # 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,
                             (1900, 1, 1, -1, 0, 0, 0, 1, -1))
         self.assertRaises(ValueError, func,
                             (1900, 1, 1, 24, 0, 0, 0, 1, -1))
         # Check minute [0, 59]
+        func((1900, 1, 1, 0, 59, 0, 0, 1, -1))
         self.assertRaises(ValueError, func,
                             (1900, 1, 1, 0, -1, 0, 0, 1, -1))
         self.assertRaises(ValueError, func,
@@ -101,15 +108,21 @@ class TimeTestCase(unittest.TestCase):
                             (1900, 1, 1, 0, 0, -1, 0, 1, -1))
         # C99 only requires allowing for one leap second, but Python's docs say
         # 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,
                             (1900, 1, 1, 0, 0, 62, 0, 1, -1))
         # No check for upper-bound day of week;
         #  value forced into range by a ``% 7`` calculation.
         # Start check at -2 since gettmarg() increments value before taking
         #  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,
                             (1900, 1, 1, 0, 0, 0, -2, 1, -1))
         # 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,
                             (1900, 1, 1, 0, 0, 0, 0, -1, -1))
         self.assertRaises(ValueError, func,
@@ -299,6 +312,8 @@ class _BaseYearTest(unittest.TestCase):
         raise NotImplementedError()
 
 class _TestAsctimeYear:
+    _format = '%d'
+
     def yearstr(self, y):
         return time.asctime((y,) + (0,) * 8).split()[-1]
 
@@ -308,8 +323,41 @@ class _TestAsctimeYear:
         self.assertEqual(self.yearstr(123456789), '123456789')
 
 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):
-        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):
         # Check that it doesn't crash for year > 9999
@@ -321,23 +369,13 @@ class _TestStrftimeYear:
         self.assertEqual(text, '12345')
         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):
         try:
             text = self.yearstr(-1)
         except ValueError:
             # strftime() is limited to [1; 9999] with Visual Studio
             return
-        self.assertIn(text, ('-1', '-001'))
+        self.assertEqual(text, self._format % -1)
 
         self.assertEqual(self.yearstr(-1234), '-1234')
         self.assertEqual(self.yearstr(-123456), '-123456')
-- 
cgit v0.12

