mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	bpo-34903: Document that some strptime formats only require 1 digit (GH-14149)
For datetime.datetime.strptime(), the leading zero for some two-digit formats is optional. This adds a footnote to the strftime/strptime documentation to reflect this fact, and adds some tests to ensure that it is true. bpo-34903
This commit is contained in:
		
							parent
							
								
									59543347d1
								
							
						
					
					
						commit
						6b9c204ee7
					
				
					 3 changed files with 56 additions and 15 deletions
				
			
		| 
						 | 
					@ -2093,7 +2093,7 @@ format codes.
 | 
				
			||||||
|           | where 0 is Sunday and 6 is     |                        |       |
 | 
					|           | where 0 is Sunday and 6 is     |                        |       |
 | 
				
			||||||
|           | Saturday.                      |                        |       |
 | 
					|           | Saturday.                      |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%d``    | Day of the month as a          | 01, 02, ..., 31        |       |
 | 
					| ``%d``    | Day of the month as a          | 01, 02, ..., 31        | \(9)  |
 | 
				
			||||||
|           | zero-padded decimal number.    |                        |       |
 | 
					|           | zero-padded decimal number.    |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%b``    | Month as locale's abbreviated  || Jan, Feb, ..., Dec    | \(1)  |
 | 
					| ``%b``    | Month as locale's abbreviated  || Jan, Feb, ..., Dec    | \(1)  |
 | 
				
			||||||
| 
						 | 
					@ -2106,29 +2106,29 @@ format codes.
 | 
				
			||||||
|           |                                || Januar, Februar, ..., |       |
 | 
					|           |                                || Januar, Februar, ..., |       |
 | 
				
			||||||
|           |                                |  Dezember (de_DE)      |       |
 | 
					|           |                                |  Dezember (de_DE)      |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%m``    | Month as a zero-padded         | 01, 02, ..., 12        |       |
 | 
					| ``%m``    | Month as a zero-padded         | 01, 02, ..., 12        | \(9)  |
 | 
				
			||||||
|           | decimal number.                |                        |       |
 | 
					|           | decimal number.                |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%y``    | Year without century as a      | 00, 01, ..., 99        |       |
 | 
					| ``%y``    | Year without century as a      | 00, 01, ..., 99        | \(9)  |
 | 
				
			||||||
|           | zero-padded decimal number.    |                        |       |
 | 
					|           | zero-padded decimal number.    |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%Y``    | Year with century as a decimal | 0001, 0002, ..., 2013, | \(2)  |
 | 
					| ``%Y``    | Year with century as a decimal | 0001, 0002, ..., 2013, | \(2)  |
 | 
				
			||||||
|           | number.                        | 2014, ..., 9998, 9999  |       |
 | 
					|           | number.                        | 2014, ..., 9998, 9999  |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%H``    | Hour (24-hour clock) as a      | 00, 01, ..., 23        |       |
 | 
					| ``%H``    | Hour (24-hour clock) as a      | 00, 01, ..., 23        | \(9)  |
 | 
				
			||||||
|           | zero-padded decimal number.    |                        |       |
 | 
					|           | zero-padded decimal number.    |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%I``    | Hour (12-hour clock) as a      | 01, 02, ..., 12        |       |
 | 
					| ``%I``    | Hour (12-hour clock) as a      | 01, 02, ..., 12        | \(9)  |
 | 
				
			||||||
|           | zero-padded decimal number.    |                        |       |
 | 
					|           | zero-padded decimal number.    |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%p``    | Locale's equivalent of either  || AM, PM (en_US);       | \(1), |
 | 
					| ``%p``    | Locale's equivalent of either  || AM, PM (en_US);       | \(1), |
 | 
				
			||||||
|           | AM or PM.                      || am, pm (de_DE)        | \(3)  |
 | 
					|           | AM or PM.                      || am, pm (de_DE)        | \(3)  |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%M``    | Minute as a zero-padded        | 00, 01, ..., 59        |       |
 | 
					| ``%M``    | Minute as a zero-padded        | 00, 01, ..., 59        | \(9)  |
 | 
				
			||||||
|           | decimal number.                |                        |       |
 | 
					|           | decimal number.                |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%S``    | Second as a zero-padded        | 00, 01, ..., 59        | \(4)  |
 | 
					| ``%S``    | Second as a zero-padded        | 00, 01, ..., 59        | \(4), |
 | 
				
			||||||
|           | decimal number.                |                        |       |
 | 
					|           | decimal number.                |                        | \(9)  |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%f``    | Microsecond as a decimal       | 000000, 000001, ...,   | \(5)  |
 | 
					| ``%f``    | Microsecond as a decimal       | 000000, 000001, ...,   | \(5)  |
 | 
				
			||||||
|           | number, zero-padded on the     | 999999                 |       |
 | 
					|           | number, zero-padded on the     | 999999                 |       |
 | 
				
			||||||
| 
						 | 
					@ -2142,19 +2142,19 @@ format codes.
 | 
				
			||||||
| ``%Z``    | Time zone name (empty string   | (empty), UTC, EST, CST |       |
 | 
					| ``%Z``    | Time zone name (empty string   | (empty), UTC, EST, CST |       |
 | 
				
			||||||
|           | if the object is naive).       |                        |       |
 | 
					|           | if the object is naive).       |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%j``    | Day of the year as a           | 001, 002, ..., 366     |       |
 | 
					| ``%j``    | Day of the year as a           | 001, 002, ..., 366     | \(9)  |
 | 
				
			||||||
|           | zero-padded decimal number.    |                        |       |
 | 
					|           | zero-padded decimal number.    |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%U``    | Week number of the year        | 00, 01, ..., 53        | \(7)  |
 | 
					| ``%U``    | Week number of the year        | 00, 01, ..., 53        | \(7), |
 | 
				
			||||||
|           | (Sunday as the first day of    |                        |       |
 | 
					|           | (Sunday as the first day of    |                        | \(9)  |
 | 
				
			||||||
|           | the week) as a zero padded     |                        |       |
 | 
					|           | the week) as a zero padded     |                        |       |
 | 
				
			||||||
|           | decimal number. All days in a  |                        |       |
 | 
					|           | decimal number. All days in a  |                        |       |
 | 
				
			||||||
|           | new year preceding the first   |                        |       |
 | 
					|           | new year preceding the first   |                        |       |
 | 
				
			||||||
|           | Sunday are considered to be in |                        |       |
 | 
					|           | Sunday are considered to be in |                        |       |
 | 
				
			||||||
|           | week 0.                        |                        |       |
 | 
					|           | week 0.                        |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%W``    | Week number of the year        | 00, 01, ..., 53        | \(7)  |
 | 
					| ``%W``    | Week number of the year        | 00, 01, ..., 53        | \(7), |
 | 
				
			||||||
|           | (Monday as the first day of    |                        |       |
 | 
					|           | (Monday as the first day of    |                        | \(9)  |
 | 
				
			||||||
|           | the week) as a decimal number. |                        |       |
 | 
					|           | the week) as a decimal number. |                        |       |
 | 
				
			||||||
|           | All days in a new year         |                        |       |
 | 
					|           | All days in a new year         |                        |       |
 | 
				
			||||||
|           | preceding the first Monday     |                        |       |
 | 
					|           | preceding the first Monday     |                        |       |
 | 
				
			||||||
| 
						 | 
					@ -2194,8 +2194,8 @@ incomplete or ambiguous ISO 8601 directives will raise a :exc:`ValueError`.
 | 
				
			||||||
| ``%u``    | ISO 8601 weekday as a decimal  | 1, 2, ..., 7           |       |
 | 
					| ``%u``    | ISO 8601 weekday as a decimal  | 1, 2, ..., 7           |       |
 | 
				
			||||||
|           | number where 1 is Monday.      |                        |       |
 | 
					|           | number where 1 is Monday.      |                        |       |
 | 
				
			||||||
+-----------+--------------------------------+------------------------+-------+
 | 
					+-----------+--------------------------------+------------------------+-------+
 | 
				
			||||||
| ``%V``    | ISO 8601 week as a decimal     | 01, 02, ..., 53        | \(8)  |
 | 
					| ``%V``    | ISO 8601 week as a decimal     | 01, 02, ..., 53        | \(8), |
 | 
				
			||||||
|           | number with Monday as          |                        |       |
 | 
					|           | number with Monday as          |                        | \(9)  |
 | 
				
			||||||
|           | the first day of the week.     |                        |       |
 | 
					|           | the first day of the week.     |                        |       |
 | 
				
			||||||
|           | Week 01 is the week containing |                        |       |
 | 
					|           | Week 01 is the week containing |                        |       |
 | 
				
			||||||
|           | Jan 4.                         |                        |       |
 | 
					|           | Jan 4.                         |                        |       |
 | 
				
			||||||
| 
						 | 
					@ -2291,6 +2291,11 @@ Notes:
 | 
				
			||||||
   :meth:`strptime` format string. Also note that ``%G`` and ``%Y`` are not
 | 
					   :meth:`strptime` format string. Also note that ``%G`` and ``%Y`` are not
 | 
				
			||||||
   interchangeable.
 | 
					   interchangeable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(9)
 | 
				
			||||||
 | 
					   When used with the :meth:`strptime` method, the leading zero is optional
 | 
				
			||||||
 | 
					   for  formats ``%d``, ``%m``, ``%H``, ``%I``, ``%M``, ``%S``, ``%J``, ``%U``,
 | 
				
			||||||
 | 
					   ``%W``, and ``%V``. Format ``%y`` does require a leading zero.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. rubric:: Footnotes
 | 
					.. rubric:: Footnotes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. [#] If, that is, we ignore the effects of Relativity
 | 
					.. [#] If, that is, we ignore the effects of Relativity
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2501,6 +2501,7 @@ def test_strptime(self):
 | 
				
			||||||
                self.assertEqual(expected, got)
 | 
					                self.assertEqual(expected, got)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        strptime = self.theclass.strptime
 | 
					        strptime = self.theclass.strptime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(strptime("+0002", "%z").utcoffset(), 2 * MINUTE)
 | 
					        self.assertEqual(strptime("+0002", "%z").utcoffset(), 2 * MINUTE)
 | 
				
			||||||
        self.assertEqual(strptime("-0002", "%z").utcoffset(), -2 * MINUTE)
 | 
					        self.assertEqual(strptime("-0002", "%z").utcoffset(), -2 * MINUTE)
 | 
				
			||||||
        self.assertEqual(
 | 
					        self.assertEqual(
 | 
				
			||||||
| 
						 | 
					@ -2535,6 +2536,40 @@ def test_strptime(self):
 | 
				
			||||||
        with self.assertRaises(ValueError): strptime("-2400", "%z")
 | 
					        with self.assertRaises(ValueError): strptime("-2400", "%z")
 | 
				
			||||||
        with self.assertRaises(ValueError): strptime("-000", "%z")
 | 
					        with self.assertRaises(ValueError): strptime("-000", "%z")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_strptime_single_digit(self):
 | 
				
			||||||
 | 
					        # bpo-34903: Check that single digit dates and times are allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        strptime = self.theclass.strptime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with self.assertRaises(ValueError):
 | 
				
			||||||
 | 
					            # %y does require two digits.
 | 
				
			||||||
 | 
					            newdate = strptime('01/02/3 04:05:06', '%d/%m/%y %H:%M:%S')
 | 
				
			||||||
 | 
					        dt1 = self.theclass(2003, 2, 1, 4, 5, 6)
 | 
				
			||||||
 | 
					        dt2 = self.theclass(2003, 1, 2, 4, 5, 6)
 | 
				
			||||||
 | 
					        dt3 = self.theclass(2003, 2, 1, 0, 0, 0)
 | 
				
			||||||
 | 
					        dt4 = self.theclass(2003, 1, 25, 0, 0, 0)
 | 
				
			||||||
 | 
					        inputs = [
 | 
				
			||||||
 | 
					            ('%d', '1/02/03 4:5:6', '%d/%m/%y %H:%M:%S', dt1),
 | 
				
			||||||
 | 
					            ('%m', '01/2/03 4:5:6', '%d/%m/%y %H:%M:%S', dt1),
 | 
				
			||||||
 | 
					            ('%H', '01/02/03 4:05:06', '%d/%m/%y %H:%M:%S', dt1),
 | 
				
			||||||
 | 
					            ('%M', '01/02/03 04:5:06', '%d/%m/%y %H:%M:%S', dt1),
 | 
				
			||||||
 | 
					            ('%S', '01/02/03 04:05:6', '%d/%m/%y %H:%M:%S', dt1),
 | 
				
			||||||
 | 
					            ('%j', '2/03 04am:05:06', '%j/%y %I%p:%M:%S',dt2),
 | 
				
			||||||
 | 
					            ('%I', '02/03 4am:05:06', '%j/%y %I%p:%M:%S',dt2),
 | 
				
			||||||
 | 
					            ('%w', '6/04/03', '%w/%U/%y', dt3),
 | 
				
			||||||
 | 
					            # %u requires a single digit.
 | 
				
			||||||
 | 
					            ('%W', '6/4/2003', '%u/%W/%Y', dt3),
 | 
				
			||||||
 | 
					            ('%V', '6/4/2003', '%u/%V/%G', dt4),
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        for reason, string, format, target in inputs:
 | 
				
			||||||
 | 
					            reason = 'test single digit ' + reason
 | 
				
			||||||
 | 
					            with self.subTest(reason=reason,
 | 
				
			||||||
 | 
					                              string=string,
 | 
				
			||||||
 | 
					                              format=format,
 | 
				
			||||||
 | 
					                              target=target):
 | 
				
			||||||
 | 
					                newdate = strptime(string, format)
 | 
				
			||||||
 | 
					                self.assertEqual(newdate, target, msg=reason)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_more_timetuple(self):
 | 
					    def test_more_timetuple(self):
 | 
				
			||||||
        # This tests fields beyond those tested by the TestDate.test_timetuple.
 | 
					        # This tests fields beyond those tested by the TestDate.test_timetuple.
 | 
				
			||||||
        t = self.theclass(2004, 12, 31, 6, 22, 33)
 | 
					        t = self.theclass(2004, 12, 31, 6, 22, 33)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Documented that in :meth:`datetime.datetime.strptime()`, the leading zero in some two-digit formats is optional. Patch by Mike Gleen.
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue