Skip to content

Commit

Permalink
utils: iso8601: strip fractional seconds (#56)
Browse files Browse the repository at this point in the history
According to ISO8601 any number of digits is permitted for fractional
seconds, the issue is that Python assumes these are microsecond, and
will fail if we have more than 6 digits.

In the event that we detect more that 6 digits, truncate the fractional
part and pass it to datetime.

Signed-off-by: Liam Beguin <[email protected]>
  • Loading branch information
liambeguin authored Apr 12, 2024
1 parent c5d194d commit 2410874
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 0 deletions.
8 changes: 8 additions & 0 deletions sigmf/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from datetime import datetime
import sys
import numpy as np
import re

from . import error

Expand All @@ -30,6 +31,13 @@ def parse_iso8601_datetime(datestr: str) -> datetime:
>>> parse_iso8601_datetime("1955-11-05T06:15:00Z")
datetime.datetime(1955, 11, 5, 6, 15)
"""
# provided string exceeds max precision -> truncate to µs
match = re.match(r"^(?P<dt>.*)(?P<frac>\.[0-9]{7,})Z$", datestr)
if match:
md = match.groupdict()
length = min(7, len(md["frac"]))
datestr = ''.join([md["dt"], md["frac"][:length], "Z"])

try:
timestamp = datetime.strptime(datestr, '%Y-%m-%dT%H:%M:%S.%fZ')
except ValueError:
Expand Down
19 changes: 19 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from datetime import datetime

import pytest

from sigmf import utils


@pytest.mark.parametrize("ts, expected", [
("1955-07-04T05:15:00Z", datetime(year=1955, month=7, day=4, hour=5, minute=15, second=00, microsecond=0)),
("2956-08-05T06:15:12Z", datetime(year=2956, month=8, day=5, hour=6, minute=15, second=12, microsecond=0)),
("3957-09-06T07:15:12.345Z", datetime(year=3957, month=9, day=6, hour=7, minute=15, second=12, microsecond=345000)),
("4958-10-07T08:15:12.0345Z", datetime(year=4958, month=10, day=7, hour=8, minute=15, second=12, microsecond=34500)),
("5959-11-08T09:15:12.000000Z", datetime(year=5959, month=11, day=8, hour=9, minute=15, second=12, microsecond=0)),
("6960-12-09T10:15:12.123456789123Z", datetime(year=6960, month=12, day=9, hour=10, minute=15, second=12, microsecond=123456)),
])
def test_parse_simple_iso8601(ts, expected):
dt = utils.parse_iso8601_datetime(ts)
assert dt == expected

0 comments on commit 2410874

Please sign in to comment.