pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/6f9c76d8d86997012acfa09fed05396aa9349bbf

stylesheet" href="https://github.githubassets.com/assets/global-d18f184ea1a06a2c.css" /> gh-152079: Fix `_datetime.fromisoformat()` mishandling a sub-second t… · python/cpython@6f9c76d · GitHub
Skip to content

Commit 6f9c76d

Browse files
gh-152079: Fix _datetime.fromisoformat() mishandling a sub-second tz offset (#152087)
Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent 05225aa commit 6f9c76d

3 files changed

Lines changed: 31 additions & 2 deletions

File tree

Lib/test/datetimetester.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3803,6 +3803,32 @@ def test_fromisoformat_utc(self):
38033803

38043804
self.assertIs(dt.tzinfo, timezone.utc)
38053805

3806+
def test_fromisoformat_utc_subsecond_offset(self):
3807+
# A UTC offset whose whole-second part is zero but with a non-zero
3808+
# microsecond part must be preserved, not collapsed to UTC.
3809+
for us in (1, -1, 999999, -999999):
3810+
with self.subTest(microseconds=us):
3811+
tz = timezone(timedelta(microseconds=us))
3812+
dt = self.theclass(2020, 6, 15, 12, 34, 56, tzinfo=tz)
3813+
rt = self.theclass.fromisoformat(dt.isoformat())
3814+
self.assertEqual(rt.utcoffset(), timedelta(microseconds=us))
3815+
self.assertEqual(rt, dt)
3816+
self.assertIsNot(rt.tzinfo, timezone.utc)
3817+
3818+
tz = timezone(timedelta(hours=5, minutes=30, seconds=15,
3819+
microseconds=123456))
3820+
dt = self.theclass(2020, 6, 15, 12, 34, 56, tzinfo=tz)
3821+
rt = self.theclass.fromisoformat(dt.isoformat())
3822+
self.assertEqual(rt.utcoffset(), tz.utcoffset(None))
3823+
self.assertEqual(rt, dt)
3824+
3825+
for tstr in ('2020-06-15T12:34:56+00:00',
3826+
'2020-06-15T12:34:56+00:00:00.000000',
3827+
'2020-06-15T12:34:56Z'):
3828+
with self.subTest(tstr=tstr):
3829+
self.assertIs(self.theclass.fromisoformat(tstr).tzinfo,
3830+
timezone.utc)
3831+
38063832
def test_fromisoformat_subclass(self):
38073833
class DateTimeSubclass(self.theclass):
38083834
pass
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :meth:`datetime.datetime.fromisoformat` in the C implementation dropping
2+
the sub-second part of a UTC offset whose whole-second part is zero, matching
3+
the pure-Python implementation.

Modules/_datetimemodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,8 +1668,8 @@ tzinfo_from_isoformat_results(int rv, int tzoffset, int tz_useconds)
16681668
{
16691669
PyObject *tzinfo;
16701670
if (rv == 1) {
1671-
// Create a timezone from offset in seconds (0 returns UTC)
1672-
if (tzoffset == 0) {
1671+
// Create a timezone from the offset (a zero offset returns UTC)
1672+
if (tzoffset == 0 && tz_useconds == 0) {
16731673
return Py_NewRef(CONST_UTC(NO_STATE));
16741674
}
16751675

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

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