From 4d4c7019aa2063a0b8742949021a028a3a96b795 Mon Sep 17 00:00:00 2001 From: Alexander Vasarab Date: Thu, 7 Jan 2021 21:09:25 -0800 Subject: [PATCH] Implement time zone support --- README.md | 27 +++++++++++++++++++++++++++ examples/config.example.ini | 1 + infoex-autowx.py | 35 ++++++++++++++++++++++++++--------- requirements.txt | 1 + 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index bebbdcb..62d15bc 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ options. `station_id = # the NRCS/MesoWest identifier for a particular station #` `desired_data = # a comma-delimited list of fields you're interested in #` `units = # either english or metric -- only applies when type is mesowest #` +`tz = # any entry from the Olson tz database e.g. America/Denver #` `path = # the filesystem path to the Python program -- only applies when type is python #` `[infoex]` @@ -206,6 +207,32 @@ or a remote web page which requires some custom parsing. Please see the program located at examples/custom-wx.example.py for a complete description of what's required. +A note on time zones +-------------------- + +This program is aware of time zones via the pytz library. The way in +which NRCS and MesoWest deal with time zones differs as follows: + +NRCS expects the request to come in the appropriate time zone, and the +data retrieved will be in the same time zone (no transformation +required before sending to InfoEx). + +MesoWest expects the request to come in UTC, and the data retrieved will +be in the same time zone (transformation from UTC to the desired time +zone is required before sending to InfoEx). + +As long as you specify the correct timezone in your configuration file, +all will be handled correctly. The list of time zones comes from the +Olson tz database. See that for more information. + +If you specify an invalid time zone, the program will exit and inform +you of such. + +Lastly, InfoEx itself is timezone aware. If you notice that the data +which makes it into your operation is inaccurate, start your +investigation with time zone-related issues and move on only once you've +ruled this out as a cause of the inaccuracy. + A note on supported measurements -------------------------------- diff --git a/examples/config.example.ini b/examples/config.example.ini index 17544ae..0408788 100644 --- a/examples/config.example.ini +++ b/examples/config.example.ini @@ -4,6 +4,7 @@ token = # MesoWest API token (ignored for NRCS) # station_id = # NRCS/MesoWest Station ID # desired_data = # Comma-separated list of values # units = # (english|metric) (ignored for NRCS) # +tz = # any Olson tz database entries e.g. America/Denver # [infoex] host = # InfoEx FTP host address # diff --git a/infoex-autowx.py b/infoex-autowx.py index dfb22a7..15adf08 100755 --- a/infoex-autowx.py +++ b/infoex-autowx.py @@ -33,6 +33,8 @@ import time from ftplib import FTP from argparse import ArgumentParser +import pytz + import requests import zeep @@ -115,6 +117,17 @@ def setup_config(config): if station['provider'] == 'python': station['path'] = config['station']['path'] + tz = 'America/Los_Angeles' + + if 'tz' in config['station']: + tz = config['station']['tz'] + + try: + station['tz'] = pytz.timezone(tz) + except pytz.exceptions.UnknownTimeZoneError: + LOG.critical("%s is not a valid timezone", tz) + sys.exit(1) + except KeyError as err: LOG.critical("%s not defined in configuration file", err) sys.exit(1) @@ -196,14 +209,14 @@ def main(): "file") sys.exit(1) - (begin_date, end_date) = setup_time_values(station['provider']) + (begin_date, end_date) = setup_time_values(station) if station['provider'] == 'python': LOG.debug("Getting custom data from external Python program") else: - LOG.debug("Getting %s data from %s to %s", + LOG.debug("Getting %s data from %s to %s (%s)", str(station['desired_data']), - str(begin_date), str(end_date)) + str(begin_date), str(end_date), end_date.tzinfo.zone) time_all_elements = time.time() @@ -251,11 +264,14 @@ def main(): LOG.debug("infoex[wx_data]: %s", str(infoex['wx_data'])) + # timezone massaging + final_end_date = end_date.astimezone(station['tz']) + # Now we only need to add in what we want to change thanks to that # abomination of a variable declaration earlier final_data[fmap['Location UUID']] = infoex['location_uuid'] - final_data[fmap['obDate']] = end_date.strftime('%m/%d/%Y') - final_data[fmap['obTime']] = end_date.strftime('%H:%M') + final_data[fmap['obDate']] = final_end_date.strftime('%m/%d/%Y') + final_data[fmap['obTime']] = final_end_date.strftime('%H:%M') for element_cd in infoex['wx_data']: if element_cd not in iemap: @@ -537,14 +553,15 @@ def upload_csv(path_to_file, infoex_data): os.remove(path_to_file) # other miscellaneous routines -def setup_time_values(provider): +def setup_time_values(station): """establish time bounds of data request(s)""" # default timezone to UTC (for MesoWest) - tz = datetime.timezone.utc + tz = pytz.utc - if provider == 'nrcs': - tz = None + # but for NRCS, use the config-specified timezone + if station['provider'] == 'nrcs': + tz = station['tz'] # floor time to nearest hour date_time = datetime.datetime.now(tz=tz) diff --git a/requirements.txt b/requirements.txt index 2aec4ac..cb9dc30 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ +pytz>=2020.1 requests>=2.0.0 zeep>=3.4.0 -- 2.30.2