Provide helpers for tz-aware datetime parsing/handling
In CKI code, datetime strings that need to be parsed can either come with or without timezone.
Internally, CKI code should always deal with non-naive (ie with timezone) datetime instances. For naive datetimes, they are assumed to be in UTC.
This is in contrast to the Python datetime module that very often assumes that naive datetimes are in local time:
Warning: Because naive datetime objects are treated by many datetime methods as local times, it is preferred to use aware datetimes to represent times in UTC.
The Python/dateutil handling/parsing code to do so is very non-obvious, so provide helpers to make sure anything ever handled internally is tz-aware.
e.g. pseudo-code for datetime_fromisoformat
:
dt = parse_datetime(datetime_string)
if dt.has_no_timezone():
dt.timezone = 'utc'
which would correctly handle the following examples:
-
2020-01-01T00:00:00
->2020-01-01T00:00:00+00:00
-
2020-01-01T00:00:00Z
->2020-01-01T00:00:00+00:00
-
2020-01-01T00:00:00+02:00
->2020-01-01T00:00:00+02:00
AC:
-
provide helpers:
-
cki_lib.misc.now_tz_utc()
-datetime.datetime.now(timezone.utc)
: !655 (merged) -
cki_lib.misc.datetime_fromisoformat_tz_utc()
- see above, but converted to UTC: !692 (merged) -
cki_lib.misc.datetime_fromisoformat()
- see above -
cki_lib.misc.datetime_fromtimestamp_utc()
-datetime.datetime.fromtimestamp(timezone.utc)
-
cki_lib.misc.now_tz()
-datetime.datetime.now().astimezone()
-> not sure this is actually needed anywhere, but would be needed for getting the local date
-
-
all uses converted:
-
dateutil.parser.parse()
-
datetime.utcnow()
-
datetime.now()
-
datetime.today()
-
datetime.utcfromtimestamp()
-
datetime.fromtimestamp()
-
time.time()
-
date.today()
- implicitly depends on the local timezone -
date.*
- not sure, but these are hard to get right regarding timezone... -
cki_lib.misc.utc_now_iso()
-
f'{naive_datetime.isoformat()}Z'
,naive_datetime.isoformat() + 'Z'
and similar - go through the list at https://github.com/frequenz-floss/frequenz-sdk-python/issues/306#issue-1654254082
-
... ??
-
-
add some linting rules so these don't get reintroduced?