Skip to content
35 changes: 20 additions & 15 deletions Doc/library/datetime.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2093,7 +2093,7 @@ format codes.
| | where 0 is Sunday and 6 is | | |
| | 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. | | |
+-----------+--------------------------------+------------------------+-------+
| ``%b`` | Month as locale's abbreviated || Jan, Feb, ..., Dec | \(1) |
Expand All @@ -2106,29 +2106,29 @@ format codes.
| | || Januar, Februar, ..., | |
| | | Dezember (de_DE) | |
+-----------+--------------------------------+------------------------+-------+
| ``%m`` | Month as a zero-padded | 01, 02, ..., 12 | |
| ``%m`` | Month as a zero-padded | 01, 02, ..., 12 | \(9) |
| | 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. | | |
+-----------+--------------------------------+------------------------+-------+
| ``%Y`` | Year with century as a decimal | 0001, 0002, ..., 2013, | \(2) |
| | 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. | | |
+-----------+--------------------------------+------------------------+-------+
| ``%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. | | |
+-----------+--------------------------------+------------------------+-------+
| ``%p`` | Locale's equivalent of either || AM, PM (en_US); | \(1), |
| | 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. | | |
+-----------+--------------------------------+------------------------+-------+
| ``%S`` | Second as a zero-padded | 00, 01, ..., 59 | \(4) |
| | decimal number. | | |
| ``%S`` | Second as a zero-padded | 00, 01, ..., 59 | \(4), |
| | decimal number. | | \(9) |
+-----------+--------------------------------+------------------------+-------+
| ``%f`` | Microsecond as a decimal | 000000, 000001, ..., | \(5) |
| | number, zero-padded on the | 999999 | |
Expand All @@ -2142,19 +2142,19 @@ format codes.
| ``%Z`` | Time zone name (empty string | (empty), UTC, EST, CST | |
| | 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. | | |
+-----------+--------------------------------+------------------------+-------+
| ``%U`` | Week number of the year | 00, 01, ..., 53 | \(7) |
| | (Sunday as the first day of | | |
| ``%U`` | Week number of the year | 00, 01, ..., 53 | \(7), |
| | (Sunday as the first day of | | \(9) |
| | the week) as a zero padded | | |
| | decimal number. All days in a | | |
| | new year preceding the first | | |
| | Sunday are considered to be in | | |
| | week 0. | | |
+-----------+--------------------------------+------------------------+-------+
| ``%W`` | Week number of the year | 00, 01, ..., 53 | \(7) |
| | (Monday as the first day of | | |
| ``%W`` | Week number of the year | 00, 01, ..., 53 | \(7), |
| | (Monday as the first day of | | \(9) |
| | the week) as a decimal number. | | |
| | All days in a new year | | |
| | preceding the first Monday | | |
Expand Down Expand Up @@ -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 | |
| | number where 1 is Monday. | | |
+-----------+--------------------------------+------------------------+-------+
| ``%V`` | ISO 8601 week as a decimal | 01, 02, ..., 53 | \(8) |
| | number with Monday as | | |
| ``%V`` | ISO 8601 week as a decimal | 01, 02, ..., 53 | \(8), |
| | number with Monday as | | \(9) |
| | the first day of the week. | | |
| | Week 01 is the week containing | | |
| | Jan 4. | | |
Expand Down Expand Up @@ -2291,6 +2291,11 @@ Notes:
:meth:`strptime` format string. Also note that ``%G`` and ``%Y`` are not
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

.. [#] If, that is, we ignore the effects of Relativity
Expand Down
33 changes: 33 additions & 0 deletions Lib/test/datetimetester.py
Original file line number Diff line number Diff line change
Expand Up @@ -2501,6 +2501,39 @@ def test_strptime(self):
self.assertEqual(expected, got)

strptime = self.theclass.strptime

# bpo-34903: Check that single digit dates and times are allowed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have a comment to delim start/end of your block, it means that you have to add a new method, like:

def test_strptime_single_digit():
  # bpo-34903: Check that single digit dates and times are allowed.
  ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to make this change but note that the code immediately preceding mine has a similar comment for bpo-34482. Could you (@vstinner) and @pganssle please confirm?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, move also the previous lines into a subtest (new method).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mikegleen It's fairly common for there to be stylistic and organizational inconsistencies in a file, because the codebase is large, old and has many contributors with different priorities (and different reviewers with different standards).

I tend to agree with Victor here. The main reason I didn't ask for this to be in a new test to start with was because, as you said, the current test suite tends towards these single monolithic tests and I prefer smaller tests and I wasn't sure if monolithic tests was a general policy or not. Given that Victor has much more experience than me with the project's conventions, I'm happy that he asked for this, because it will make me feel more confident in making smaller tests in the future. 😄

Also, as an aside, I'd like to thank you for your ongoing efforts in this PR, I think we're in the home stretch 😉

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)

# end bpo-34903

self.assertEqual(strptime("+0002", "%z").utcoffset(), 2 * MINUTE)
self.assertEqual(strptime("-0002", "%z").utcoffset(), -2 * MINUTE)
self.assertEqual(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Documented that in :meth:datetime.datetime.strptime(), the leading zero in some two-digit formats is optional. Patch by Mike Gleen.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Documented that in :meth:datetime.datetime.strptime(), the leading zero in some two-digit formats is optional. Patch by Mike Gleen.
Documented that in :meth:`datetime.datetime.strptime()`, the leading zero in some two-digit formats is optional. Patch by Mike Gleen.

This needs backticks so Sphinx can turn it into a link to the relevant method.