Skip to content

Commit 8ffdcbc

Browse files
authored
Fix BLF timestamp conversion (#1273)
* fix rounding error * fix test and add type annotations
1 parent 4d9b32c commit 8ffdcbc

File tree

2 files changed

+31
-11
lines changed

2 files changed

+31
-11
lines changed

can/io/blf.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@
1717
import datetime
1818
import time
1919
import logging
20-
from typing import List, BinaryIO, Generator, Union
20+
from typing import List, BinaryIO, Generator, Union, Tuple, Optional, cast
2121

2222
from ..message import Message
2323
from ..util import len2dlc, dlc2len, channel2int
2424
from ..typechecking import StringPathLike
2525
from .generic import FileIOMessageWriter, MessageReader
2626

2727

28+
TSystemTime = Tuple[int, int, int, int, int, int, int, int]
29+
30+
2831
class BLFParseError(Exception):
2932
"""BLF file could not be parsed correctly."""
3033

@@ -97,11 +100,11 @@ class BLFParseError(Exception):
97100
TIME_ONE_NANS = 0x00000002
98101

99102

100-
def timestamp_to_systemtime(timestamp):
103+
def timestamp_to_systemtime(timestamp: float) -> TSystemTime:
101104
if timestamp is None or timestamp < 631152000:
102105
# Probably not a Unix timestamp
103-
return (0, 0, 0, 0, 0, 0, 0, 0)
104-
t = datetime.datetime.fromtimestamp(timestamp)
106+
return 0, 0, 0, 0, 0, 0, 0, 0
107+
t = datetime.datetime.fromtimestamp(round(timestamp, 3))
105108
return (
106109
t.year,
107110
t.month,
@@ -110,11 +113,11 @@ def timestamp_to_systemtime(timestamp):
110113
t.hour,
111114
t.minute,
112115
t.second,
113-
int(round(t.microsecond / 1000.0)),
116+
t.microsecond // 1000,
114117
)
115118

116119

117-
def systemtime_to_timestamp(systemtime):
120+
def systemtime_to_timestamp(systemtime: TSystemTime) -> float:
118121
try:
119122
t = datetime.datetime(
120123
systemtime[0],
@@ -125,7 +128,7 @@ def systemtime_to_timestamp(systemtime):
125128
systemtime[6],
126129
systemtime[7] * 1000,
127130
)
128-
return time.mktime(t.timetuple()) + systemtime[7] / 1000.0
131+
return t.timestamp()
129132
except ValueError:
130133
return 0
131134

@@ -154,8 +157,8 @@ def __init__(self, file: Union[StringPathLike, BinaryIO]) -> None:
154157
self.file_size = header[10]
155158
self.uncompressed_size = header[11]
156159
self.object_count = header[12]
157-
self.start_timestamp = systemtime_to_timestamp(header[14:22])
158-
self.stop_timestamp = systemtime_to_timestamp(header[22:30])
160+
self.start_timestamp = systemtime_to_timestamp(cast(TSystemTime, header[14:22]))
161+
self.stop_timestamp = systemtime_to_timestamp(cast(TSystemTime, header[22:30]))
159162
# Read rest of header
160163
self.file.read(header[1] - FILE_HEADER_STRUCT.size)
161164
self._tail = b""
@@ -405,8 +408,12 @@ def __init__(
405408
raise BLFParseError("Unexpected file format")
406409
self.uncompressed_size = header[11]
407410
self.object_count = header[12]
408-
self.start_timestamp = systemtime_to_timestamp(header[14:22])
409-
self.stop_timestamp = systemtime_to_timestamp(header[22:30])
411+
self.start_timestamp: Optional[float] = systemtime_to_timestamp(
412+
cast(TSystemTime, header[14:22])
413+
)
414+
self.stop_timestamp: Optional[float] = systemtime_to_timestamp(
415+
cast(TSystemTime, header[22:30])
416+
)
410417
# Jump to the end of the file
411418
self.file.seek(0, 2)
412419
else:

test/logformats_test.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from datetime import datetime
2121

2222
import can
23+
from can.io import blf
2324

2425
from .data.example_data import (
2526
TEST_MESSAGES_BASE,
@@ -659,6 +660,18 @@ def test_can_error_frame_ext(self):
659660
self.assertMessagesEqual(actual, [expected] * 2)
660661
self.assertEqual(actual[0].channel, expected.channel)
661662

663+
def test_timestamp_to_systemtime(self):
664+
self.assertAlmostEqual(
665+
1636485425.999,
666+
blf.systemtime_to_timestamp(blf.timestamp_to_systemtime(1636485425.998908)),
667+
places=3,
668+
)
669+
self.assertAlmostEqual(
670+
1636485426.0,
671+
blf.systemtime_to_timestamp(blf.timestamp_to_systemtime(1636485425.999908)),
672+
places=3,
673+
)
674+
662675

663676
class TestCanutilsFileFormat(ReaderWriterTest):
664677
"""Tests can.CanutilsLogWriter and can.CanutilsLogReader"""

0 commit comments

Comments
 (0)