From e57d1b6321917ab5c6cb4380de20fd9a92bcf020 Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Fri, 16 Jun 2023 14:49:17 +0100 Subject: [PATCH 01/17] Add NEWS.d entry --- .../next/Library/2023-06-16-14-49-00.gh-issue-102450.BoEfh3.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2023-06-16-14-49-00.gh-issue-102450.BoEfh3.rst diff --git a/Misc/NEWS.d/next/Library/2023-06-16-14-49-00.gh-issue-102450.BoEfh3.rst b/Misc/NEWS.d/next/Library/2023-06-16-14-49-00.gh-issue-102450.BoEfh3.rst new file mode 100644 index 00000000000000..8013aba21e2a64 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-06-16-14-49-00.gh-issue-102450.BoEfh3.rst @@ -0,0 +1 @@ +Add missing ISO-8601 24:00 alternative to midnight of next day to :meth:`datetime.datetime.fromisoformat()` and :meth:`datetime.time.fromisoformat()`. From d711dafdb23d23ed248686b122a5b4a33c33b462 Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Fri, 16 Jun 2023 11:26:18 +0100 Subject: [PATCH 02/17] Allow ISO-8601 24:00 alternative to midnight on datetime.time.fromisoformat() --- Modules/_datetimemodule.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 8562e0ca0bbbab..63e9167ff2a26a 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -5004,6 +5004,10 @@ time_fromisoformat(PyObject *cls, PyObject *tstr) { return NULL; } + if (hour == 24 && minute == 0 && second == 0 && microsecond == 0) { + hour = 0; + } + PyObject *t; if ( (PyTypeObject *)cls == TIME_TYPE(NO_STATE)) { t = new_time(hour, minute, second, microsecond, tzinfo, 0); From f32aa970e7a738c3b4402ef0c5799bbdacd84408 Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Fri, 16 Jun 2023 11:54:23 +0100 Subject: [PATCH 03/17] Allow ISO-8601 24:00 alternative to midnight on datetime.datetime.fromisoformat() --- Modules/_datetimemodule.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 63e9167ff2a26a..c8d95bc3f97ba5 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -5865,6 +5865,22 @@ datetime_fromisoformat(PyObject *cls, PyObject *dtstr) goto error; } + if ( + (hour == 24 && minute == 0 && second == 0 && microsecond == 0) && // provided alternate to midnight of next day + (month <= 12 && day <= days_in_month(year, month)) // month and day component was previously valid + ) { + // Calculate midnight of the next day + hour = 0; + day += 1; + if (day > days_in_month(year, month)) { + day = 1; + month += 1; + if (month > 12) { + month = 1; + year += 1; + } + } + } PyObject *dt = new_datetime_subclass_ex(year, month, day, hour, minute, second, microsecond, tzinfo, cls); From d52bf410ce63f84e3d74b11a1c5f1c93e0194ea8 Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Fri, 16 Jun 2023 14:52:20 +0100 Subject: [PATCH 04/17] Add NEWS.d entry --- .../next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst diff --git a/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst b/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst new file mode 100644 index 00000000000000..8013aba21e2a64 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst @@ -0,0 +1 @@ +Add missing ISO-8601 24:00 alternative to midnight of next day to :meth:`datetime.datetime.fromisoformat()` and :meth:`datetime.time.fromisoformat()`. From 699dfcb50f439b05cd01997a1b82aa6d37e3c45f Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Fri, 16 Jun 2023 15:55:20 +0100 Subject: [PATCH 05/17] Improve error message when hour is 24 and minute/second/microsecond is not 0 --- Modules/_datetimemodule.c | 43 +++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index c8d95bc3f97ba5..0b53f4635c4fa8 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -5004,8 +5004,12 @@ time_fromisoformat(PyObject *cls, PyObject *tstr) { return NULL; } - if (hour == 24 && minute == 0 && second == 0 && microsecond == 0) { - hour = 0; + if (hour == 24) { + if (minute == 0 && second == 0 && microsecond == 0) { + hour = 0; + } else { + goto invalid_iso_midnight; + } } PyObject *t; @@ -5019,6 +5023,10 @@ time_fromisoformat(PyObject *cls, PyObject *tstr) { Py_DECREF(tzinfo); return t; +invalid_iso_midnight: + PyErr_SetString(PyExc_ValueError, "minute, second, and microsecond must be 0 when hour is 24"); + return NULL; + invalid_string_error: PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", tstr); return NULL; @@ -5865,20 +5873,21 @@ datetime_fromisoformat(PyObject *cls, PyObject *dtstr) goto error; } - if ( - (hour == 24 && minute == 0 && second == 0 && microsecond == 0) && // provided alternate to midnight of next day - (month <= 12 && day <= days_in_month(year, month)) // month and day component was previously valid - ) { - // Calculate midnight of the next day - hour = 0; - day += 1; - if (day > days_in_month(year, month)) { - day = 1; - month += 1; - if (month > 12) { - month = 1; - year += 1; + if ((hour == 24) && (month <= 12 && day <= days_in_month(year, month))) { + if (minute == 0 && second == 0 && microsecond == 0) { + // Calculate midnight of the next day + hour = 0; + day += 1; + if (day > days_in_month(year, month)) { + day = 1; + month += 1; + if (month > 12) { + month = 1; + year += 1; + } } + } else { + goto invalid_iso_midnight; } } PyObject *dt = new_datetime_subclass_ex(year, month, day, hour, minute, @@ -5888,6 +5897,10 @@ datetime_fromisoformat(PyObject *cls, PyObject *dtstr) Py_DECREF(dtstr_clean); return dt; +invalid_iso_midnight: + PyErr_SetString(PyExc_ValueError, "minute, second, and microsecond must be 0 when hour is 24"); + return NULL; + invalid_string_error: PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", dtstr); From 6e46433245a346e223c6998642340d0d399df9fa Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Sat, 17 Jun 2023 22:09:13 +0100 Subject: [PATCH 06/17] Add tests for 24:00 fromisoformat --- Lib/test/datetimetester.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index aef24e11393f6a..f2c9672296804e 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -3342,6 +3342,9 @@ def test_fromisoformat_datetime_examples(self): ('2025-01-02T03:04:05,678+00:00:10', self.theclass(2025, 1, 2, 3, 4, 5, 678000, tzinfo=timezone(timedelta(seconds=10)))), + ('2025-01-02T24:00:00', self.theclass(2025, 1, 3, 0, 0, 0)), + ('2025-01-31T24:00:00', self.theclass(2025, 2, 1, 0, 0, 0)), + ('2025-12-31T24:00:00', self.theclass(2026, 1, 1, 0, 0, 0)) ] for input_str, expected in examples: @@ -3378,6 +3381,11 @@ def test_fromisoformat_fails_datetime(self): '2009-04-19T12:30:45.123456-05:00a', # Extra text '2009-04-19T12:30:45.123-05:00a', # Extra text '2009-04-19T12:30:45-05:00a', # Extra text + '2009-04-19T24:00:00.000001', # Has non-zero microseconds on 24:00 + '2009-04-19T24:00:01.000000', # Has non-zero seconds on 24:00 + '2009-04-19T24:01:00.000000', # Has non-zero minutes on 24:00 + '2009-04-32T24:00:00.000000', # Day is invalid before wrapping due to 24:00 + '2009-13-01T24:00:00.000000', # Month is invalid before wrapping due to 24:00 ] for bad_str in bad_strs: From 040da2c341404eeadb050939db51c15b01ac57c6 Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Sat, 17 Jun 2023 22:59:18 +0100 Subject: [PATCH 07/17] Remove duplicate call to days_in_month() by storing in variable --- Modules/_datetimemodule.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 0b53f4635c4fa8..8cb62ee8933f4e 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -5873,22 +5873,26 @@ datetime_fromisoformat(PyObject *cls, PyObject *dtstr) goto error; } - if ((hour == 24) && (month <= 12 && day <= days_in_month(year, month))) { - if (minute == 0 && second == 0 && microsecond == 0) { - // Calculate midnight of the next day - hour = 0; - day += 1; - if (day > days_in_month(year, month)) { - day = 1; - month += 1; - if (month > 12) { - month = 1; - year += 1; + if ((hour == 24) && (month <= 12)) { + int d_in_month = days_in_month(year, month); + if (day <= d_in_month) { + if (minute == 0 && second == 0 && microsecond == 0) { + // Calculate midnight of the next day + hour = 0; + day += 1; + if (day > d_in_month) { + day = 1; + month += 1; + if (month > 12) { + month = 1; + year += 1; + } } + } else { + goto invalid_iso_midnight; } - } else { - goto invalid_iso_midnight; } + } PyObject *dt = new_datetime_subclass_ex(year, month, day, hour, minute, second, microsecond, tzinfo, cls); From 4833d68082da51b62752eddffc1eeb9881c3c46f Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Sat, 17 Jun 2023 22:59:35 +0100 Subject: [PATCH 08/17] Add Python implementation --- Lib/_pydatetime.py | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index f8e121eb79a04d..098004fcbb91ab 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -463,6 +463,16 @@ def _parse_isoformat_time(tstr): time_comps = _parse_hh_mm_ss_ff(timestr) + hour, minute, second, microsecond = time_comps + became_next_day = False + if (hour == 24): + if not all(time_comp == 0 for time_comp in time_comps[1:]): + raise ValueError("minute, second, and microsecond must be 0 when hour is 24") + + hour = 0 + time_comps[0] = hour + became_next_day = True + tzi = None if tz_pos == len_str and tstr[-1] == 'Z': tzi = timezone.utc @@ -488,14 +498,14 @@ def _parse_isoformat_time(tstr): else: tzsign = -1 if tstr[tz_pos - 1] == '-' else 1 - td = timedelta(hours=tz_comps[0], minutes=tz_comps[1], - seconds=tz_comps[2], microseconds=tz_comps[3]) + td = timedelta(hours=hour, minutes=minute, + seconds=second, microseconds=microsecond) tzi = timezone(tzsign * td) time_comps.append(tzi) - return time_comps + return time_comps, became_next_day # tuple[int, int, int] -> tuple[int, int, int] version of date.fromisocalendar def _isoweek_to_gregorian(year, week, day): @@ -1588,7 +1598,7 @@ def fromisoformat(cls, time_string): time_string = time_string.removeprefix('T') try: - return cls(*_parse_isoformat_time(time_string)) + return cls(*_parse_isoformat_time(time_string)[0]) except Exception: raise ValueError(f'Invalid isoformat string: {time_string!r}') @@ -1902,10 +1912,25 @@ def fromisoformat(cls, date_string): if tstr: try: - time_components = _parse_isoformat_time(tstr) + time_components, became_next_day = _parse_isoformat_time(tstr) except ValueError: raise ValueError( f'Invalid isoformat string: {date_string!r}') from None + else: + if became_next_day: + year, month, day = date_components + + # Only wrap day/month when it was previously valid + if month <= 12 and day <= (days_in_month := _days_in_month(year, month)): + # Calculate midnight of the next day + day += 1 + if day > days_in_month: + day = 1 + month += 1 + if month > 12: + month = 1 + year += 1 + date_components = [year, month, day] else: time_components = [0, 0, 0, 0, None] From c71764f4200ba8c62d5cffda67b82eb0615c7aaa Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Sat, 17 Jun 2023 23:10:39 +0100 Subject: [PATCH 09/17] Fix Lint --- Lib/_pydatetime.py | 1 - Modules/_datetimemodule.c | 1 - 2 files changed, 2 deletions(-) diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index 098004fcbb91ab..9a16e52109be30 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -1919,7 +1919,6 @@ def fromisoformat(cls, date_string): else: if became_next_day: year, month, day = date_components - # Only wrap day/month when it was previously valid if month <= 12 and day <= (days_in_month := _days_in_month(year, month)): # Calculate midnight of the next day diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 8cb62ee8933f4e..3b7340e69bb455 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -5892,7 +5892,6 @@ datetime_fromisoformat(PyObject *cls, PyObject *dtstr) goto invalid_iso_midnight; } } - } PyObject *dt = new_datetime_subclass_ex(year, month, day, hour, minute, second, microsecond, tzinfo, cls); From 0b92a1cf1739d21298da0766b373d656a478a0e8 Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Sat, 17 Jun 2023 23:36:06 +0100 Subject: [PATCH 10/17] Fix differing error msg in datetime.fromisoformat implementations when 24hrs has non-zero time component(s) --- Lib/_pydatetime.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index 9a16e52109be30..2aac4fc061ce45 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -465,13 +465,14 @@ def _parse_isoformat_time(tstr): hour, minute, second, microsecond = time_comps became_next_day = False + error_from_components = False if (hour == 24): - if not all(time_comp == 0 for time_comp in time_comps[1:]): - raise ValueError("minute, second, and microsecond must be 0 when hour is 24") - - hour = 0 - time_comps[0] = hour - became_next_day = True + if all(time_comp == 0 for time_comp in time_comps[1:]): + hour = 0 + time_comps[0] = hour + became_next_day = True + else: + error_from_components = True tzi = None if tz_pos == len_str and tstr[-1] == 'Z': @@ -505,7 +506,7 @@ def _parse_isoformat_time(tstr): time_comps.append(tzi) - return time_comps, became_next_day + return time_comps, became_next_day, error_from_components # tuple[int, int, int] -> tuple[int, int, int] version of date.fromisocalendar def _isoweek_to_gregorian(year, week, day): @@ -1912,11 +1913,14 @@ def fromisoformat(cls, date_string): if tstr: try: - time_components, became_next_day = _parse_isoformat_time(tstr) + time_components, became_next_day, error_from_components = _parse_isoformat_time(tstr) except ValueError: raise ValueError( f'Invalid isoformat string: {date_string!r}') from None else: + if error_from_components: + raise ValueError("minute, second, and microsecond must be 0 when hour is 24") + if became_next_day: year, month, day = date_components # Only wrap day/month when it was previously valid From c9db98ba1c33b7ab60b7fb71395a7e379819af11 Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Sun, 18 Jun 2023 08:42:31 +0100 Subject: [PATCH 11/17] Fix using time components inside tzinfo in Python implementation --- Lib/_pydatetime.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index 2aac4fc061ce45..154e6ebb9c5131 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -499,8 +499,8 @@ def _parse_isoformat_time(tstr): else: tzsign = -1 if tstr[tz_pos - 1] == '-' else 1 - td = timedelta(hours=hour, minutes=minute, - seconds=second, microseconds=microsecond) + td = timedelta(hours=tz_comps[0], minutes=tz_comps[1], + seconds=tz_comps[2], microseconds=tz_comps[3]) tzi = timezone(tzsign * td) From 004a5fffa10c522f628a94125c18e827ef9faa99 Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Sun, 18 Jun 2023 08:44:04 +0100 Subject: [PATCH 12/17] Don't parse tzinfo in C implementation when invalid iso midnight --- Modules/_datetimemodule.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 3b7340e69bb455..58b365334869da 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -4997,13 +4997,6 @@ time_fromisoformat(PyObject *cls, PyObject *tstr) { goto invalid_string_error; } - PyObject *tzinfo = tzinfo_from_isoformat_results(rv, tzoffset, - tzimicrosecond); - - if (tzinfo == NULL) { - return NULL; - } - if (hour == 24) { if (minute == 0 && second == 0 && microsecond == 0) { hour = 0; @@ -5012,6 +5005,13 @@ time_fromisoformat(PyObject *cls, PyObject *tstr) { } } + PyObject *tzinfo = tzinfo_from_isoformat_results(rv, tzoffset, + tzimicrosecond); + + if (tzinfo == NULL) { + return NULL; + } + PyObject *t; if ( (PyTypeObject *)cls == TIME_TYPE(NO_STATE)) { t = new_time(hour, minute, second, microsecond, tzinfo, 0); From f182e2e2bd1f389e4f76ef14a4331bf0fb79da18 Mon Sep 17 00:00:00 2001 From: TizzySaurus Date: Sun, 18 Jun 2023 08:45:05 +0100 Subject: [PATCH 13/17] Remove duplicated variable in datetime test assertion line --- Lib/test/datetimetester.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index f2c9672296804e..3c4b3a4099ed70 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -4320,7 +4320,7 @@ def test_fromisoformat_timezone(self): with self.subTest(tstr=tstr): t_rt = self.theclass.fromisoformat(tstr) - assert t == t_rt, t_rt + assert t == t_rt def test_fromisoformat_timespecs(self): time_bases = [ From 1b65671e346d454915578c5e502891dc40a60a4d Mon Sep 17 00:00:00 2001 From: Izan Robinson Date: Wed, 25 Sep 2024 09:44:41 +0100 Subject: [PATCH 14/17] Add self to acknowledgements --- Misc/ACKS | 1 + .../next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst | 1 + 2 files changed, 2 insertions(+) diff --git a/Misc/ACKS b/Misc/ACKS index ef0f403950255b..b2529601a2f71a 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1553,6 +1553,7 @@ Carl Robben Ben Roberts Mark Roberts Andy Robinson +Izan "TizzySaurus" Robinson Jim Robinson Yolanda Robla Daniel Rocco diff --git a/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst b/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst index 8013aba21e2a64..b56954e6811dac 100644 --- a/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst +++ b/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst @@ -1 +1,2 @@ Add missing ISO-8601 24:00 alternative to midnight of next day to :meth:`datetime.datetime.fromisoformat()` and :meth:`datetime.time.fromisoformat()`. +Patch by Izan "TizzySaurus" Robinson (tizzysaurus@gmail.com) \ No newline at end of file From ae85372add0f6e82a93ff28075820e007425ae38 Mon Sep 17 00:00:00 2001 From: Izan Robinson Date: Wed, 25 Sep 2024 09:52:33 +0100 Subject: [PATCH 15/17] Remove duplicate NEWS entry --- .../next/Library/2023-06-16-14-49-00.gh-issue-102450.BoEfh3.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Library/2023-06-16-14-49-00.gh-issue-102450.BoEfh3.rst diff --git a/Misc/NEWS.d/next/Library/2023-06-16-14-49-00.gh-issue-102450.BoEfh3.rst b/Misc/NEWS.d/next/Library/2023-06-16-14-49-00.gh-issue-102450.BoEfh3.rst deleted file mode 100644 index 8013aba21e2a64..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-06-16-14-49-00.gh-issue-102450.BoEfh3.rst +++ /dev/null @@ -1 +0,0 @@ -Add missing ISO-8601 24:00 alternative to midnight of next day to :meth:`datetime.datetime.fromisoformat()` and :meth:`datetime.time.fromisoformat()`. From 9d02f82532796ee52578ce7a29f5aa0e43be6585 Mon Sep 17 00:00:00 2001 From: Izan Robinson Date: Wed, 25 Sep 2024 09:55:05 +0100 Subject: [PATCH 16/17] Linting --- .../Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst b/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst index b56954e6811dac..abfad5fa63b777 100644 --- a/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst +++ b/Misc/NEWS.d/next/Library/2023-06-16-14-52-00.gh-issue-102450.MfeR6A.rst @@ -1,2 +1,2 @@ -Add missing ISO-8601 24:00 alternative to midnight of next day to :meth:`datetime.datetime.fromisoformat()` and :meth:`datetime.time.fromisoformat()`. -Patch by Izan "TizzySaurus" Robinson (tizzysaurus@gmail.com) \ No newline at end of file +Add missing ISO-8601 24:00 alternative to midnight of next day to :meth:`datetime.datetime.fromisoformat` and :meth:`datetime.time.fromisoformat`. +Patch by Izan "TizzySaurus" Robinson (tizzysaurus@gmail.com) From 2ccb2a220c4e60d3fccbc2e3feab9796fd3b9d2e Mon Sep 17 00:00:00 2001 From: Izan Robinson Date: Wed, 25 Sep 2024 11:06:18 +0100 Subject: [PATCH 17/17] Add missing test case for when wrapping the year makes it invalid (too large) --- Lib/test/datetimetester.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 3c4b3a4099ed70..16aff186eb69f7 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -3386,6 +3386,7 @@ def test_fromisoformat_fails_datetime(self): '2009-04-19T24:01:00.000000', # Has non-zero minutes on 24:00 '2009-04-32T24:00:00.000000', # Day is invalid before wrapping due to 24:00 '2009-13-01T24:00:00.000000', # Month is invalid before wrapping due to 24:00 + '9999-12-31T24:00:00.000000', # Year is invalid after wrapping due to 24:00 ] for bad_str in bad_strs: pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy