8000 datetime.datetime.isoformat parses input incorrectly · Issue #115225 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

datetime.datetime.isoformat parses input incorrectly #115225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
xitop opened this issue Feb 9, 2024 · 4 comments
Closed

datetime.datetime.isoformat parses input incorrectly #115225

xitop opened this issue Feb 9, 2024 · 4 comments
Labels
type-bug An unexpected behavior, bug, or error

Comments

@xitop
Copy link
xitop commented Feb 9, 2024

Bug report

Bug description:

import datetime as dt
print(dt.time.fromisoformat("T1250.50"))

Actual result is 12:50:00.500000, but according to ISO 8601 the string represents 12:50:30
(50 and half minutes, format "HHMM.mmm", because "a decimal fraction may be added
to the lowest order time element present"
)

if partial minutes are not supported by Python as stated in the docs, a ValueError should be raised.

Affected are versions 3.10+.

CPython versions tested on:

3.12

Operating systems tested on:

Linux

Linked PRs

@pganssle
Copy link
Member

if partial minutes are not supported by Python as stated in the docs, a ValueError should be raised.

Fractional hours and minutes should not be supported. We should change the time.fromisoformat docs to reflect that and raise a ValueError in this case.

The reason why they are not supported is that we decided that a string like T12:00.50 is much more likely to be a typo for something like T12:00:50 than to be an actual fractional hour or minute, because this is a particularly obscure feature of ISO-8601.

@xitop How did you discover this? Were you using something that actually generates a string like that, or was this an attempt to find bugs? I'm curious to know if my reasoning about no one really using these features is correct.

@xitop
Copy link
Author
xitop commented Feb 12, 2024

@xitop How did you discover this?

Pure chance. I was working on a software processing time intervals with a parser accepting various formats. I read the .fromisoformat() docs and used such string in a unit test as an example of incorrect input. As you wrote, it looks like a typo, so it is likely that the parser encounters input like that.

benchatt added a commit to benchatt/cpython that referenced this issue May 21, 2024
Some time strings that contain fractional hours or minutes are permitted
by ISO 8601, but such strings are very unlikely to be intentional. The
current parser does not parse such strings correctly or raise an error.
This change raises a ValueError when hours or minutes contain a decimal mark.
benchatt added a commit to benchatt/cpython that referenced this issue May 22, 2024
Some time strings that contain fractional hours or minutes are permitted
by ISO 8601, but such strings are very unlikely to be intentional. The
current parser does not parse such strings correctly or raise an error.
This change raises a ValueError when hours or minutes contain a decimal mark.
benchatt added a commit to benchatt/cpython that referenced this issue May 24, 2024
Some time strings that contain fractional hours or minutes are permitted
by ISO 8601, but such strings are very unlikely to be intentional. The
current parser does not parse such strings correctly or raise an error.
This change raises a ValueError when hours or minutes contain a decimal mark.
pganssle pushed a commit that referenced this issue Jun 5, 2024
Some time strings that contain fractional hours or minutes are permitted
by ISO 8601, but such strings are very unlikely to be intentional. The
current parser does not parse such strings correctly or raise an error.
This change raises a ValueError when hours or minutes contain a decimal mark.

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
barneygale pushed a commit to barneygale/cpython that referenced this issue Jun 5, 2024
…thon#119339)

Some time strings that contain fractional hours or minutes are permitted
by ISO 8601, but such strings are very unlikely to be intentional. The
current parser does not parse such strings correctly or raise an error.
This change raises a ValueError when hours or minutes contain a decimal mark.

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
noahbkim pushed a commit to hudson-trading/cpython that referenced this issue Jul 11, 2024
…thon#119339)

Some time strings that contain fractional hours or minutes are permitted
by ISO 8601, but such strings are very unlikely to be intentional. The
current parser does not parse such strings correctly or raise an error.
This change raises a ValueError when hours or minutes contain a decimal mark.

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
estyxx pushed a commit to estyxx/cpython that referenced this issue Jul 17, 2024
…thon#119339)

Some time strings that contain fractional hours or minutes are permitted
by ISO 8601, but such strings are very unlikely to be intentional. The
current parser does not parse such strings correctly or raise an error.
This change raises a ValueError when hours or minutes contain a decimal mark.

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
@StanFromIreland
Copy link
Contributor

The implementation causes odd behavior for the pure Python implementation

>>> import _pydatetime as dt
... print(dt.time.fromisoformat("T1250.50"))
... 
Traceback (most recent call last):
  File "/usr/local/lib/python3.14/_pydatetime.py", line 1633, in fromisoformat
    return cls(*_parse_isoformat_time(time_string)[0])
                ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/_pydatetime.py", line 466, in _parse_isoformat_time
    time_comps = _parse_hh_mm_ss_ff(timestr)
  File "/usr/local/lib/python3.14/_pydatetime.py", line 418, in _parse_hh_mm_ss_ff
    time_comps[comp] = int(tstr[pos:pos+2])
                       ~~~^^^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: '.5'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<python-input-0>", line 2, in <module>
    print(dt.time.fromisoformat("T1250.50"))
          ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/_pydatetime.py", line 1635, in fromisoformat
    raise ValueError(f'Invalid
9C36
 isoformat string: {time_string!r}')
ValueError: Invalid isoformat string: '1250.50'

C for reference:

>>> import datetime as dt
... print(dt.time.fromisoformat("T1250.50"))
... 
Traceback (most recent call last):
  File "<python-input-1>", line 2, in <module>
    print(dt.time.fromisoformat("T1250.50"))
          ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
ValueError: Invalid isoformat string: 'T1250.50'

@encukou
Copy link
Member
encukou commented Mar 12, 2025

The PR was merged some time ago.

The implementation causes odd behavior for the pure Python implementation

IMO, exception chaining is perfectly fine. The final exception is the same; we don't really need to hide the reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
Archived in project
Development

No branches or pull requests

4 participants
0