Skip to content

Commit 2630fb3

Browse files
authored
ASCReader: Improve datetime parsing and support double-defined AM/PM cases (#2009)
* ASCReader: Improve datetime parsing and support double-defined AM/PM cases * Fixed code formatting and add a news fragment for PR 2009 * Updated formatting of logformats_test.py * Updated test for cross-platform compatibility and (hopefully) fixed formatting for good now * Corrected micro- to milliseconds
1 parent 58860af commit 2630fb3

File tree

3 files changed

+64
-20
lines changed

3 files changed

+64
-20
lines changed

can/io/asc.py

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -116,41 +116,50 @@ def _extract_header(self) -> None:
116116

117117
@staticmethod
118118
def _datetime_to_timestamp(datetime_string: str) -> float:
119-
# ugly locale independent solution
120119
month_map = {
121-
"Jan": 1,
122-
"Feb": 2,
123-
"Mar": 3,
124-
"Apr": 4,
125-
"May": 5,
126-
"Jun": 6,
127-
"Jul": 7,
128-
"Aug": 8,
129-
"Sep": 9,
130-
"Oct": 10,
131-
"Nov": 11,
132-
"Dec": 12,
133-
"Mär": 3,
134-
"Mai": 5,
135-
"Okt": 10,
136-
"Dez": 12,
120+
"jan": 1,
121+
"feb": 2,
122+
"mar": 3,
123+
"apr": 4,
124+
"may": 5,
125+
"jun": 6,
126+
"jul": 7,
127+
"aug": 8,
128+
"sep": 9,
129+
"oct": 10,
130+
"nov": 11,
131+
"dec": 12,
132+
"mär": 3,
133+
"mai": 5,
134+
"okt": 10,
135+
"dez": 12,
137136
}
138-
for name, number in month_map.items():
139-
datetime_string = datetime_string.replace(name, str(number).zfill(2))
140137

141138
datetime_formats = (
142139
"%m %d %I:%M:%S.%f %p %Y",
143140
"%m %d %I:%M:%S %p %Y",
144141
"%m %d %H:%M:%S.%f %Y",
145142
"%m %d %H:%M:%S %Y",
143+
"%m %d %H:%M:%S.%f %p %Y",
144+
"%m %d %H:%M:%S %p %Y",
146145
)
146+
147+
datetime_string_parts = datetime_string.split(" ", 1)
148+
month = datetime_string_parts[0].strip().lower()
149+
150+
try:
151+
datetime_string_parts[0] = f"{month_map[month]:02d}"
152+
except KeyError:
153+
raise ValueError(f"Unsupported month abbreviation: {month}") from None
154+
datetime_string = " ".join(datetime_string_parts)
155+
147156
for format_str in datetime_formats:
148157
try:
149158
return datetime.strptime(datetime_string, format_str).timestamp()
150159
except ValueError:
151160
continue
152161

153-
raise ValueError(f"Incompatible datetime string {datetime_string}")
162+
raise ValueError(f"Unsupported datetime format: '{datetime_string}'")
154163

155164
def _extract_can_id(self, str_can_id: str, msg_kwargs: dict[str, Any]) -> None:
156165
if str_can_id[-1:].lower() == "x":

doc/changelog.d/2009.changed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improved datetime parsing and added support for “double-defined” datetime strings (such as, e.g., `"30 15:06:13.191 pm 2017"`) for ASCReader class.

test/logformats_test.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,40 @@ def test_write(self):
680680

681681
self.assertEqual(expected_file.read_text(), actual_file.read_text())
682682

683+
@parameterized.expand(
684+
[
685+
(
686+
"May 27 04:09:35.000 pm 2014",
687+
datetime(2014, 5, 27, 16, 9, 35, 0).timestamp(),
688+
),
689+
(
690+
"Mai 27 04:09:35.000 pm 2014",
691+
datetime(2014, 5, 27, 16, 9, 35, 0).timestamp(),
692+
),
693+
(
694+
"Apr 28 10:44:52.480 2022",
695+
datetime(2022, 4, 28, 10, 44, 52, 480000).timestamp(),
696+
),
697+
(
698+
"Sep 30 15:06:13.191 2017",
699+
datetime(2017, 9, 30, 15, 6, 13, 191000).timestamp(),
700+
),
701+
(
702+
"Sep 30 15:06:13.191 pm 2017",
703+
datetime(2017, 9, 30, 15, 6, 13, 191000).timestamp(),
704+
),
705+
(
706+
"Sep 30 15:06:13.191 am 2017",
707+
datetime(2017, 9, 30, 15, 6, 13, 191000).timestamp(),
708+
),
709+
]
710+
)
711+
def test_datetime_to_timestamp(
712+
self, datetime_string: str, expected_timestamp: float
713+
):
714+
timestamp = can.ASCReader._datetime_to_timestamp(datetime_string)
715+
self.assertAlmostEqual(timestamp, expected_timestamp)
716+
683717

684718
class TestBlfFileFormat(ReaderWriterTest):
685719
"""Tests can.BLFWriter and can.BLFReader.

0 commit comments

Comments
 (0)