Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] DAQ: Assume naive human-readable timestamps w/o timezone information to be in UTC #124

Draft
wants to merge 1 commit into
base: ecowitt-passkey
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ in progress
- CI: Update to Grafana 9.3.0
- DAQ: Mask ``PASSKEY`` variable coming from HTTP, emitted by Ecowitt

Breaking changes
----------------

- DAQ: Obtain naive timestamps as UTC by default, instead of CET


.. _kotori-0.27.0:

Expand Down
14 changes: 9 additions & 5 deletions kotori/io/protocol/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import arrow
import datetime
from six import text_type
from dateutil.tz import gettz
from dateutil.tz import gettz, tzutc
from dateutil.parser import parse
from pyramid.settings import asbool
from twisted.web import http
Expand Down Expand Up @@ -177,23 +177,27 @@ def slugify_datettime(dstring):
return arrow.get(dstring).to('utc').format('YYYYMMDDTHHmmss')


def parse_timestamp(timestamp):
def parse_timestamp(timestamp, use_utc=False):

if isinstance(timestamp, text_type):

# FIXME: Maybe use system timezone here by default.
# TODO: Make configurable via channel settings.

# HACK: Assume CET (Europe/Berlin) for human readable timestamp w/o timezone offset
# Handle naive human-readable timestamps w/o timezone offset.
qualified = any([token in timestamp for token in ['Z', '+', ' CET', ' CEST']])
if not qualified:
timestamp += ' CET'
# Assume CET (Europe/Berlin) (default), or UTC.
if use_utc:
timestamp += ' UTC'
else:
timestamp += ' CET'

# Parse datetime string
# Remark: Maybe use pandas.tseries.tools.parse_time_string?
# TODO: Cache results of call to gettz to improve performance
berlin = gettz('Europe/Berlin')
tzinfos = {'CET': berlin, 'CEST': berlin}
tzinfos = {'UTC': tzutc(), 'CET': berlin, 'CEST': berlin}
timestamp = parse(timestamp, tzinfos=tzinfos)

return timestamp
6 changes: 6 additions & 0 deletions test/test_ecowitt.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import json

from kotori.io.protocol.util import parse_timestamp
from test.settings.mqttkit import PROCESS_DELAY_HTTP, influx_sensors, settings
from test.util import http_form_sensor, sleep

Expand Down Expand Up @@ -85,4 +87,8 @@ def test_ecowitt_post(machinery, create_influxdb, reset_influxdb):
# Make sure this will not be public.
assert "PASSKEY" not in record

# Make sure decoding the timestamp works.
print(record["time"])
assert parse_timestamp(record["time"]) == parse_timestamp("2023-02-20 16:02:19", use_utc=True)

yield record