Skip to content

Commit 452b417

Browse files
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 (cherry picked from commit 6b9c204) Co-authored-by: Mike Gleen <[email protected]>
1 parent 624c9a2 commit 452b417

File tree

3 files changed

+56
-15
lines changed

3 files changed

+56
-15
lines changed

Doc/library/datetime.rst

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,7 +2076,7 @@ format codes.
20762076
| | where 0 is Sunday and 6 is | | |
20772077
| | Saturday. | | |
20782078
+-----------+--------------------------------+------------------------+-------+
2079-
| ``%d`` | Day of the month as a | 01, 02, ..., 31 | |
2079+
| ``%d`` | Day of the month as a | 01, 02, ..., 31 | \(9) |
20802080
| | zero-padded decimal number. | | |
20812081
+-----------+--------------------------------+------------------------+-------+
20822082
| ``%b`` | Month as locale's abbreviated || Jan, Feb, ..., Dec | \(1) |
@@ -2089,29 +2089,29 @@ format codes.
20892089
| | || Januar, Februar, ..., | |
20902090
| | | Dezember (de_DE) | |
20912091
+-----------+--------------------------------+------------------------+-------+
2092-
| ``%m`` | Month as a zero-padded | 01, 02, ..., 12 | |
2092+
| ``%m`` | Month as a zero-padded | 01, 02, ..., 12 | \(9) |
20932093
| | decimal number. | | |
20942094
+-----------+--------------------------------+------------------------+-------+
2095-
| ``%y`` | Year without century as a | 00, 01, ..., 99 | |
2095+
| ``%y`` | Year without century as a | 00, 01, ..., 99 | \(9) |
20962096
| | zero-padded decimal number. | | |
20972097
+-----------+--------------------------------+------------------------+-------+
20982098
| ``%Y`` | Year with century as a decimal | 0001, 0002, ..., 2013, | \(2) |
20992099
| | number. | 2014, ..., 9998, 9999 | |
21002100
+-----------+--------------------------------+------------------------+-------+
2101-
| ``%H`` | Hour (24-hour clock) as a | 00, 01, ..., 23 | |
2101+
| ``%H`` | Hour (24-hour clock) as a | 00, 01, ..., 23 | \(9) |
21022102
| | zero-padded decimal number. | | |
21032103
+-----------+--------------------------------+------------------------+-------+
2104-
| ``%I`` | Hour (12-hour clock) as a | 01, 02, ..., 12 | |
2104+
| ``%I`` | Hour (12-hour clock) as a | 01, 02, ..., 12 | \(9) |
21052105
| | zero-padded decimal number. | | |
21062106
+-----------+--------------------------------+------------------------+-------+
21072107
| ``%p`` | Locale's equivalent of either || AM, PM (en_US); | \(1), |
21082108
| | AM or PM. || am, pm (de_DE) | \(3) |
21092109
+-----------+--------------------------------+------------------------+-------+
2110-
| ``%M`` | Minute as a zero-padded | 00, 01, ..., 59 | |
2110+
| ``%M`` | Minute as a zero-padded | 00, 01, ..., 59 | \(9) |
21112111
| | decimal number. | | |
21122112
+-----------+--------------------------------+------------------------+-------+
2113-
| ``%S`` | Second as a zero-padded | 00, 01, ..., 59 | \(4) |
2114-
| | decimal number. | | |
2113+
| ``%S`` | Second as a zero-padded | 00, 01, ..., 59 | \(4), |
2114+
| | decimal number. | | \(9) |
21152115
+-----------+--------------------------------+------------------------+-------+
21162116
| ``%f`` | Microsecond as a decimal | 000000, 000001, ..., | \(5) |
21172117
| | number, zero-padded on the | 999999 | |
@@ -2125,19 +2125,19 @@ format codes.
21252125
| ``%Z`` | Time zone name (empty string | (empty), UTC, EST, CST | |
21262126
| | if the object is naive). | | |
21272127
+-----------+--------------------------------+------------------------+-------+
2128-
| ``%j`` | Day of the year as a | 001, 002, ..., 366 | |
2128+
| ``%j`` | Day of the year as a | 001, 002, ..., 366 | \(9) |
21292129
| | zero-padded decimal number. | | |
21302130
+-----------+--------------------------------+------------------------+-------+
2131-
| ``%U`` | Week number of the year | 00, 01, ..., 53 | \(7) |
2132-
| | (Sunday as the first day of | | |
2131+
| ``%U`` | Week number of the year | 00, 01, ..., 53 | \(7), |
2132+
| | (Sunday as the first day of | | \(9) |
21332133
| | the week) as a zero padded | | |
21342134
| | decimal number. All days in a | | |
21352135
| | new year preceding the first | | |
21362136
| | Sunday are considered to be in | | |
21372137
| | week 0. | | |
21382138
+-----------+--------------------------------+------------------------+-------+
2139-
| ``%W`` | Week number of the year | 00, 01, ..., 53 | \(7) |
2140-
| | (Monday as the first day of | | |
2139+
| ``%W`` | Week number of the year | 00, 01, ..., 53 | \(7), |
2140+
| | (Monday as the first day of | | \(9) |
21412141
| | the week) as a decimal number. | | |
21422142
| | All days in a new year | | |
21432143
| | preceding the first Monday | | |
@@ -2177,8 +2177,8 @@ incomplete or ambiguous ISO 8601 directives will raise a :exc:`ValueError`.
21772177
| ``%u`` | ISO 8601 weekday as a decimal | 1, 2, ..., 7 | |
21782178
| | number where 1 is Monday. | | |
21792179
+-----------+--------------------------------+------------------------+-------+
2180-
| ``%V`` | ISO 8601 week as a decimal | 01, 02, ..., 53 | \(8) |
2181-
| | number with Monday as | | |
2180+
| ``%V`` | ISO 8601 week as a decimal | 01, 02, ..., 53 | \(8), |
2181+
| | number with Monday as | | \(9) |
21822182
| | the first day of the week. | | |
21832183
| | Week 01 is the week containing | | |
21842184
| | Jan 4. | | |
@@ -2274,6 +2274,11 @@ Notes:
22742274
:meth:`strptime` format string. Also note that ``%G`` and ``%Y`` are not
22752275
interchangeable.
22762276

2277+
(9)
2278+
When used with the :meth:`strptime` method, the leading zero is optional
2279+
for formats ``%d``, ``%m``, ``%H``, ``%I``, ``%M``, ``%S``, ``%J``, ``%U``,
2280+
``%W``, and ``%V``. Format ``%y`` does require a leading zero.
2281+
22772282
.. rubric:: Footnotes
22782283

22792284
.. [#] If, that is, we ignore the effects of Relativity

Lib/test/datetimetester.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2387,6 +2387,7 @@ def test_strptime(self):
23872387
self.assertEqual(expected, got)
23882388

23892389
strptime = self.theclass.strptime
2390+
23902391
self.assertEqual(strptime("+0002", "%z").utcoffset(), 2 * MINUTE)
23912392
self.assertEqual(strptime("-0002", "%z").utcoffset(), -2 * MINUTE)
23922393
self.assertEqual(
@@ -2421,6 +2422,40 @@ def test_strptime(self):
24212422
with self.assertRaises(ValueError): strptime("-2400", "%z")
24222423
with self.assertRaises(ValueError): strptime("-000", "%z")
24232424

2425+
def test_strptime_single_digit(self):
2426+
# bpo-34903: Check that single digit dates and times are allowed.
2427+
2428+
strptime = self.theclass.strptime
2429+
2430+
with self.assertRaises(ValueError):
2431+
# %y does require two digits.
2432+
newdate = strptime('01/02/3 04:05:06', '%d/%m/%y %H:%M:%S')
2433+
dt1 = self.theclass(2003, 2, 1, 4, 5, 6)
2434+
dt2 = self.theclass(2003, 1, 2, 4, 5, 6)
2435+
dt3 = self.theclass(2003, 2, 1, 0, 0, 0)
2436+
dt4 = self.theclass(2003, 1, 25, 0, 0, 0)
2437+
inputs = [
2438+
('%d', '1/02/03 4:5:6', '%d/%m/%y %H:%M:%S', dt1),
2439+
('%m', '01/2/03 4:5:6', '%d/%m/%y %H:%M:%S', dt1),
2440+
('%H', '01/02/03 4:05:06', '%d/%m/%y %H:%M:%S', dt1),
2441+
('%M', '01/02/03 04:5:06', '%d/%m/%y %H:%M:%S', dt1),
2442+
('%S', '01/02/03 04:05:6', '%d/%m/%y %H:%M:%S', dt1),
2443+
('%j', '2/03 04am:05:06', '%j/%y %I%p:%M:%S',dt2),
2444+
('%I', '02/03 4am:05:06', '%j/%y %I%p:%M:%S',dt2),
2445+
('%w', '6/04/03', '%w/%U/%y', dt3),
2446+
# %u requires a single digit.
2447+
('%W', '6/4/2003', '%u/%W/%Y', dt3),
2448+
('%V', '6/4/2003', '%u/%V/%G', dt4),
2449+
]
2450+
for reason, string, format, target in inputs:
2451+
reason = 'test single digit ' + reason
2452+
with self.subTest(reason=reason,
2453+
string=string,
2454+
format=format,
2455+
target=target):
2456+
newdate = strptime(string, format)
2457+
self.assertEqual(newdate, target, msg=reason)
2458+
24242459
def test_more_timetuple(self):
24252460
# This tests fields beyond those tested by the TestDate.test_timetuple.
24262461
t = self.theclass(2004, 12, 31, 6, 22, 33)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Documented that in :meth:`datetime.datetime.strptime()`, the leading zero in some two-digit formats is optional. Patch by Mike Gleen.

0 commit comments

Comments
 (0)