From d8e5d03b01a87704424f5259cf6bd977274fd6ee Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 22 Mar 2021 20:21:12 -0700 Subject: [PATCH] naive updated_epoch timestamp calculation added --- jc/parsers/upower.py | 53 +++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/jc/parsers/upower.py b/jc/parsers/upower.py index ef20b0f4..0497a1b9 100644 --- a/jc/parsers/upower.py +++ b/jc/parsers/upower.py @@ -1,5 +1,7 @@ """jc - JSON CLI output utility `upower` command output parser +Calculated epoch time fields are naive (i.e. based on the local time of the system the parser is run on) since there is no unambiguous timezone information in the `upower` command output. + Usage (cli): $ upower -d | jc --upower @@ -125,8 +127,8 @@ Examples: } ] """ -# import locale -# from datetime import datetime, timezone +import locale +from datetime import datetime import jc.utils @@ -165,6 +167,7 @@ def process(proc_data): "native_path": string, "power_supply": boolean, "updated": string, + "updated_epoch": integer, # works best with C locale. null if conversion fails "updated_seconds_ago": integer, "has_history": boolean, "has_statistics": boolean, @@ -223,38 +226,22 @@ def process(proc_data): entry['updated'] = ' '.join(updated_list[:-3]) entry['updated_seconds_ago'] = int(updated_list[-3]) - # Removing attempted epoch conversions since, depending on locale, timezone info may not be present in output. - # May investigate if there is a way to reliably convert the datetime string to an epoch timestamp - # if the timezone is present in a future release. - # - # If we assume current OS timezone, that works for interactive use: upower -d | jc --upower - # - # But, this wont necessarily convert timestamps correctly if converting text output sourced from another system: - # cat upower.out | jc --upower - # - # In this scenario, we don't always know what timezone was used on the source, so timestamp calculations will - # probably be wrong. - # # try C locale. If that fails, try current locale. If that fails, give up - # entry['updated_epoch'] = None - # try: - # locale.setlocale(locale.LC_TIME, None) - # epoch_dt = datetime.strptime(entry['updated'], '%c').astimezone(tz=None) - # entry['updated_epoch'] = int(epoch_dt.strftime('%s')) - # entry['date_from_timestamp_local'] = datetime.fromtimestamp(entry['updated_epoch']).strftime('%c') - # entry['updated_epoch_utc'] = int(epoch_dt.replace(tzinfo=timezone.utc).strftime('%s')) - # entry['date_from_timestamp_utc'] = datetime.fromtimestamp(entry['updated_epoch_utc']).strftime('%c') - # except Exception: - # try: - # locale.setlocale(locale.LC_TIME, '') - # entry['updated_epoch'] = int(datetime.strptime(entry['updated'], '%c').astimezone(tz=timezone.utc).strftime('%s')) - - # except Exception: - # pass - # finally: - # locale.setlocale(locale.LC_TIME, None) - # finally: - # locale.setlocale(locale.LC_TIME, None) + entry['updated_epoch'] = None + try: + locale.setlocale(locale.LC_TIME, None) + epoch_dt = datetime.strptime(entry['updated'], '%c') + entry['updated_epoch'] = int(epoch_dt.strftime('%s')) + except Exception: + try: + locale.setlocale(locale.LC_TIME, '') + entry['updated_epoch'] = int(epoch_dt.strftime('%s')) + except Exception: + pass + finally: + locale.setlocale(locale.LC_TIME, None) + finally: + locale.setlocale(locale.LC_TIME, None) # top level boolean conversions bool_list = ['power_supply', 'has_history', 'has_statistics', 'on_battery', 'lid_is_closed', 'lid_is_present']