Repository navigation
Add new format code to strptime for when microsecond is optional #100929
Description
Feature or enhancement
I propose that a new % format code(s) be added to strptime to allow parsing of timestamps which are either whole seconds, or fractions of a second.
The current %f format code will throw an error if the input string has no microsecond component.
Pitch
As an example, I would like to pass both of the following strings with the same code.
import datetime as dt
fmt = "%Y-%m-%d %H:%M:%S.%f"
ts = [
"2023-01-01 09:10:13.513",
"2023-01-01 09:10:13"
]
for s in ts:
dt.datetime.strptime(s, fmt)This currently fails with:
Traceback (most recent call last):
File "main.py", line 9, in <module>
dt.datetime.strptime(s, fmt)
File "/home/ec2-user/.pyenv/versions/3.8.11/lib/python3.8/_strptime.py", line 568, in _strptime_datetime
tt, fraction, gmtoff_fraction = _strptime(data_string, format)
File "/home/ec2-user/.pyenv/versions/3.8.11/lib/python3.8/_strptime.py", line 349, in _strptime
raise ValueError("time data %r does not match format %r" %
ValueError: time data '2023-01-01 09:10:13' does not match format '%Y-%m-%d %H:%M:%S.%f'In my code I could write a try/except block to catch the error and try with a different string. I think it would be nice if strptime could handle that for me. Although I do know that the implementation of this function depends on the system, so this might be a tricky change.
There's a few options.
Option A
Add a new format code which is similar to %f, but can handle an empty microsecond component.
I note that %F is not yet taken, so we could use that.
Note that %f today doesn't expect a ..
So in the above example you'd use %Y-%m-%d %H:%M:%S%F.
Option B
Add a new format code for parsing seconds and optionally microseconds in one go. I note that %s is not yet taken, so we could use that.
So in the above example you'd use %Y-%m-%d %H:%M:%s.
Option C
Add [] to make a component optional.
So in the above example you'd use %Y-%m-%d %H:%M:%S[.%f].
My guess is that this would be quite a substantial change.
Option D
Modify the arguments to strptime so that it can take a list of format strings. It tries them in order until it one succeeds.
So in the above example you'd use
dt.datetime.strptime(s, ["%Y-%m-%d %H:%M:%S.%f", "%Y-%m-%d %H:%M:%S"])Since a list of strings, and a single string are both iterators of strings, this might be a bit fiddly to implement. You could add a new formats argument, and require that either format or formats is passed in. Although that kind of clutters the function signature.
Previous discussion
https://bugs.python.org/issue1982 @abalkin
https://bugs.python.org/issue1158
Linked PRs
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Activity
BlackAce21 commentedon Jul 3, 2023
Work around for this problem in case anyone else ends up here and just wants something that works. Combination of proposed option C and D in the OP. Apologies if dropping a code block isn't proper etiquette
StanFromIreland commentedon Mar 23, 2025
This would be a change to the Python module
_strptime.py, and not an extension-module. I will look into it todaypganssle commentedon Mar 24, 2025
I think the format you specified is already something you can parse with
fromisoformat. Obviously this feature is more general than that, but if the vast majority of the time the person is trying to solve the problem of possibly-truncated ISO formatted datetime strings (as has been the case in previous iterations of this issue), then I think we can just leave it withfromisofornatfor those use cases, and try-except blocks for the rare exceptions.encukou commentedon Mar 24, 2025
@mdavis-xyz, would
fromisoformatwork for you?mdavis-xyz commentedon Mar 24, 2025
My use case typically involves dates like
2025/03/23 06:15:00(e.g. from here)..fromisoformatcan't handle the slashes. (I don't know why I used dashes in my original post. I probably modified an example from the Python docs.)I suppose I can use something like
dt.datetime.fromisoformat(t1.replace('/', '-')). (Although that isn't quite as seamless as using a plain date string, e.g. withpandas.read_csv(myfile, date_format=""))StanFromIreland commentedon Aug 29, 2025
Seeing as reporter has a simple work-around, closing.