Skip to content

Commit cbe6981

Browse files
committed
Fix timestamp parsing to always include milliseconds (#2683)
* fix datetime parsing when ms are zero * small refactoring
1 parent ee4c163 commit cbe6981

File tree

2 files changed

+20
-9
lines changed

2 files changed

+20
-9
lines changed

src/huggingface_hub/utils/_datetime.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,20 @@ def parse_datetime(date_string: str) -> datetime:
4646
If `date_string` cannot be parsed.
4747
"""
4848
try:
49-
# Datetime ending with a Z means "UTC". We parse the date and then explicitly
50-
# set the timezone to UTC.
51-
# See https://en.wikipedia.org/wiki/ISO_8601#Coordinated_Universal_Time_(UTC)
52-
# Taken from https://stackoverflow.com/a/3168394.
53-
if len(date_string) == 30:
54-
# Means timezoned-timestamp with nanoseconds precision. We need to truncate the last 3 digits.
55-
date_string = date_string[:-4] + "Z"
56-
dt = datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%S.%fZ")
57-
return dt.replace(tzinfo=timezone.utc) # Set explicit timezone
49+
# Normalize the string to always have 6 digits of fractional seconds
50+
if date_string.endswith("Z"):
51+
# Case 1: No decimal point (e.g., "2024-11-16T00:27:02Z")
52+
if "." not in date_string:
53+
# No fractional seconds - insert .000000
54+
date_string = date_string[:-1] + ".000000Z"
55+
# Case 2: Has decimal point (e.g., "2022-08-19T07:19:38.123456789Z")
56+
else:
57+
# Get the fractional and base parts
58+
base, fraction = date_string[:-1].split(".")
59+
# fraction[:6] takes first 6 digits and :0<6 pads with zeros if less than 6 digits
60+
date_string = f"{base}.{fraction[:6]:0<6}Z"
61+
62+
return datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=timezone.utc)
5863
except ValueError as e:
5964
raise ValueError(
6065
f"Cannot parse '{date_string}' as a datetime. Date string is expected to"

tests/test_utils_datetime.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ def test_parse_datetime(self):
2020
datetime(2022, 8, 19, 7, 19, 38, 123456, tzinfo=timezone.utc),
2121
)
2222

23+
# Test without milliseconds (should add .000)
24+
self.assertEqual(
25+
parse_datetime("2024-11-16T00:27:02Z"),
26+
datetime(2024, 11, 16, 0, 27, 2, 0, tzinfo=timezone.utc),
27+
)
28+
2329
with pytest.raises(ValueError, match=r".*Cannot parse '2022-08-19T07:19:38' as a datetime.*"):
2430
parse_datetime("2022-08-19T07:19:38")
2531

0 commit comments

Comments
 (0)