Skip to content

Commit c98dca6

Browse files
Fix time zone handling
1 parent 1ad5d35 commit c98dca6

File tree

3 files changed

+15
-10
lines changed

3 files changed

+15
-10
lines changed

src/rctclient/cli.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# SPDX-License-Identifier: GPL-3.0-only
99

1010
import logging
11+
import pytz
1112
import select
1213
import socket
1314
import sys
@@ -28,6 +29,7 @@
2829
from .utils import decode_value, encode_value
2930

3031
log = logging.getLogger('rctclient.cli')
32+
gmt = pytz.timezone('GMT')
3133

3234

3335
@click.group()
@@ -174,7 +176,7 @@ def read_value(ctx, port: int, host: str, id: Optional[str], name: Optional[str]
174176
is_ev = oinfo.response_data_type == DataType.EVENT_TABLE
175177
if is_ts or is_ev:
176178
sock.send(make_frame(command=Command.WRITE, id=oinfo.object_id,
177-
payload=encode_value(DataType.INT32, int(datetime.now().timestamp()))))
179+
payload=encode_value(DataType.INT32, int(datetime.now().replace(tzinfo=gmt).timestamp()))))
178180
else:
179181
sock.send(make_frame(command=Command.READ, id=oinfo.object_id))
180182
try:

src/rctclient/utils.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Copyright 2020-2021, Stefan Valouch (svalouch)
44
# SPDX-License-Identifier: GPL-3.0-only
55

6+
import pytz
67
import struct
78
from datetime import datetime
89
from typing import overload, Dict, Tuple, Union
@@ -16,6 +17,7 @@
1617

1718
from .types import DataType, EventEntry
1819

20+
timezone = pytz.timezone('Europe/Berlin')
1921

2022
# pylint: disable=invalid-name
2123
def CRC16(data: Union[bytes, bytearray]) -> int:
@@ -187,12 +189,12 @@ def _decode_timeseries(data: bytes) -> Tuple[datetime, Dict[datetime, int]]:
187189
'''
188190
Helper function to decode the timeseries type.
189191
'''
190-
timestamp = datetime.fromtimestamp(struct.unpack('>I', data[0:4])[0])
192+
timestamp = timezone.localize(datetime.utcfromtimestamp(struct.unpack('>I', data[0:4])[0]))
191193
tsval: Dict[datetime, int] = dict()
192194
assert len(data) % 4 == 0, 'Data should be divisible by 4'
193195
assert int(len(data) / 4 % 2) == 1, 'Data should be an even number of 4-byte pairs plus the starting timestamp'
194196
for pair in range(0, int(len(data) / 4 - 1), 2):
195-
pair_ts = datetime.fromtimestamp(struct.unpack('>I', data[4 + pair * 4:4 + pair * 4 + 4])[0])
197+
pair_ts = timezone.localize(datetime.utcfromtimestamp(struct.unpack('>I', data[4 + pair * 4:4 + pair * 4 + 4])[0]))
196198
pair_val = struct.unpack('>f', data[4 + pair * 4 + 4:4 + pair * 4 + 4 + 4])[0]
197199
tsval[pair_ts] = pair_val
198200
return timestamp, tsval
@@ -202,15 +204,15 @@ def _decode_event_table(data: bytes) -> Tuple[datetime, Dict[datetime, EventEntr
202204
'''
203205
Helper function to decode the event table type.
204206
'''
205-
timestamp = datetime.fromtimestamp(struct.unpack('>I', data[0:4])[0])
207+
timestamp = timezone.localize(datetime.utcfromtimestamp(struct.unpack('>I', data[0:4])[0]))
206208
tabval: Dict[datetime, EventEntry] = dict()
207209
assert len(data) % 4 == 0
208210
assert (len(data) - 4) % 20 == 0
209211
for pair in range(0, int(len(data) / 4 - 1), 5):
210212
# this is most likely a single byte of information, but this is not sure yet
211213
# entry_type = bytes([struct.unpack('>I', data[4 + pair * 4:4 + pair * 4 + 4])[0]]).decode('ascii')
212214
entry_type = struct.unpack('>I', data[4 + pair * 4:4 + pair * 4 + 4])[0]
213-
timestamp = datetime.fromtimestamp(struct.unpack('>I', data[4 + pair * 4 + 4:4 + pair * 4 + 8])[0])
215+
timestamp = timezone.localize(datetime.utcfromtimestamp(struct.unpack('>I', data[4 + pair * 4 + 4:4 + pair * 4 + 8])[0]))
214216
element2 = struct.unpack('>I', data[4 + pair * 4 + 8:4 + pair * 4 + 12])[0]
215217
element3 = struct.unpack('>I', data[4 + pair * 4 + 12:4 + pair * 4 + 16])[0]
216218
element4 = struct.unpack('>I', data[4 + pair * 4 + 16:4 + pair * 4 + 20])[0]
@@ -225,8 +227,8 @@ def _decode_event_table(data: bytes) -> Tuple[datetime, Dict[datetime, EventEntr
225227
# value_old=value_old, value_new=value_new)
226228
# the rest is assumed to be range-based events
227229
# else:
228-
# timestamp_end = datetime.fromtimestamp(
229-
# struct.unpack('>I', data[4 + pair * 4 + 12:4 + pair * 4 + 16])[0])
230+
# timestamp_end = timezone.localize(datetime.utcfromtimestamp(
231+
# struct.unpack('>I', data[4 + pair * 4 + 12:4 + pair * 4 + 16])[0]))
230232
# object_id = struct.unpack('>I', data[4 + pair * 4 + 16:4 + pair * 4 + 20])[0]
231233
# tabval[timestamp] = EventEntry(timestamp=timestamp, object_id=object_id, entry_type=entry_type,
232234
# timestamp_end=timestamp_end)

tools/timeseries2csv.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
# pylint: disable=too-many-arguments,too-many-locals
3131

32+
gmt = pytz.timezone('GMT')
3233

3334
def datetime_range(start: datetime, end: datetime, delta: relativedelta):
3435
'''
@@ -114,7 +115,7 @@ def timeseries2csv(host: str, port: int, output: Optional[str], header_format: b
114115
sys.exit(1)
115116

116117
timezone = pytz.timezone(time_zone)
117-
now = datetime.now()
118+
now = datetime.now(timezone)
118119

119120
if resolution == 'minutes':
120121
oid_names = ['logger.minutes_ubat_log_ts', 'logger.minutes_ul3_log_ts', 'logger.minutes_ub_log_ts',
@@ -209,7 +210,7 @@ def timeseries2csv(host: str, port: int, output: Optional[str], header_format: b
209210
while highest_ts > ts_start and not iter_end:
210211
cprint(f'\ttimestamp: {highest_ts}')
211212
sock.send(make_frame(command=Command.WRITE, id=oid.object_id,
212-
payload=encode_value(DataType.INT32, int(highest_ts.timestamp()))))
213+
payload=encode_value(DataType.INT32, int(highest_ts.replace(tzinfo=gmt).timestamp()))))
213214

214215
rframe = ReceiveFrame()
215216
while True:
@@ -313,7 +314,7 @@ def timeseries2csv(host: str, port: int, output: Optional[str], header_format: b
313314

314315
for bts, btval in datetable.items():
315316
if btval: # there may be holes in the data
316-
writer.writerow([timezone.localize(bts).isoformat('T')] + [str(btval[name]) for name in names])
317+
writer.writerow([bts.isoformat('T')] + [str(btval[name]) for name in names])
317318

318319
if output != '-':
319320
fd.flush()

0 commit comments

Comments
 (0)