cpython
cpython copied to clipboard
Support `%:z` in `datetime.datetime.strptime`
Bug report
Bug description:
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes documents "strftime() and strptime() Format Codes". It mentions the new %:z variant of %z, introduced in Python 3.12
>>> datetime.datetime.strptime("2023-07-17T13:58:49-07:00", "%Y-%m-%dT%H:%M:%S%z")
datetime.datetime(2023, 7, 17, 13, 58, 49, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
>>> datetime.datetime.strptime("2023-07-17T13:58:49-07:00", "%Y-%m-%dT%H:%M:%S%:z")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.12/_strptime.py", line 554, in _strptime_datetime
tt, fraction, gmtoff_fraction = _strptime(data_string, format)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/_strptime.py", line 325, in _strptime
raise ValueError("'%s' is a bad directive in format '%s'" %
ValueError: ':' is a bad directive in format '%Y-%m-%dT%H:%M:%S%:z'
But passing "%:z" to strptime raises an error. This is a bug because strptime and strftime should have the same format codes, according to the docs.
Since %z already parses this format when passed to strptime, I think %:z should just do the same thing.
Workaround: Change %:z to %z in your format string for strptime.
CPython versions tested on:
3.12
Operating systems tested on:
Linux
Linked PRs
- gh-122142
Wouldn't %:z have to reject -0400?
Reasonable question. Shouldn't %z reject -04:00? It doesn't, currently.
Both should parse the alternative format, or neither, for the sake of consistency.
The current behavior for %z is old (predates %:z from 3.12). I would argue for both to avoid breaking backwards compatibility.
In my view : is optional for %z, so it's not used in strftime(), while it's required in %:z.
If we enforce this, this actually allows something new instead of an alternative way to do it:
There should be one-- and preferably only one --obvious way to do it.
This should probably be labeled as a new feature.
I think either implementation would be an improvement. I raise no objection :)
@Eclips4 can you add the feature label?
I'll be taking care of this one
As dicussed, we need to have consistency across strptime and strftime, while keeping backwards compatibility.
%zand%:zwork as expected instrftime, so no need to change anything there.%zdoes what it should instrptime, while in addition allowing%:z-formatted strings too (see third comment). We should keep this behavior for backwards compatibility.%:zfails instrptime. We should allow%:zthere and make it parse only%:z-formatted strings.
I added a PR addressing the issue: https://github.com/python/cpython/pull/122142
This was implemented for strftime without consideration for strptime in https://github.com/python/cpython/commit/023c51d9d8e2fd91069eea2bf12e373f1c71e9d2 3 years ago. I would consider this a documentation bug, since it does imply it should be available on strptime also, but implementing it is a feature now.
Any reason why strptime doesn't return a datetime object with timezone, when %Z is used, either?
$ python
Python 3.13.5 (main, Jun 11 2025, 15:36:57) [GCC 14.3.0] on linux
>>> from datetime import datetime
>>> datetime.strptime("20250913-CEST1251", "%Y%m%d-%Z%H%M")
datetime.datetime(2025, 9, 13, 12, 51)
>>> datetime.strptime("20250913-UTC1251", "%Y%m%d-%Z%H%M")
datetime.datetime(2025, 9, 13, 12, 51)
>>> datetime.strptime("20250913-1251", "%Y%m%d-%H%M")
datetime.datetime(2025, 9, 13, 12, 51)
Edit: Nevermind, see https://github.com/python/cpython/issues/66571
This has now been implemented and merged in #136961