We have the need to convert an incoming datetime string into a UTC datetime string. The incoming string is in this format:
'01/28/2022 12:00 AM'
with intended output as:
'2022-01-28T08:00:00Z'
The string has no declared timezone but is supposed to be PST. We'd like to code this in a way that allows for multiple timezones and date string formats. We can get this working using the following code:
from datetime import datetime
import pytz
UTC_TIME_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
PROVIDER_DATETIME_FORMAT = '%m/%d/%Y %I:%M %p'
PROVIDER_TIMEZONE = 'America/Los_Angeles'
def dt_string_to_utc_converter(datetime_str)
utc_timezone = pytz.utc
pst_timezone = pytz.timezone(PROVIDER_TIMEZONE)
naive_date = datetime.strptime(datetime_str, PROVIDER_DATETIME_FORMAT)
pst_date = pst_timezone.localize(naive_date)
utc_date = pst_date.astimezone(utc_timezone)
utc_date_str = utc_date.strftime(UTC_TIME_FORMAT)
return utc_date_str
However (for reasons I won't get into) we have been asked to not use the pytz library and instead stick to Python's native datetime, and dateutil libraries. Currently we are committed to Python 3.8.
I've tried a number of things things using datetime's strptime and dateutil's parser, but all to dead ends so far. Are there any obvious patterns i am missing?
Thanks
CodePudding user response:
Well, after some more digging I managed to find refs here and here that laid out the basics of what I needed. Final code looks like this:
from datetime import datetime
from dateutil import tz, parser, utils
UTC_TIME_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
PROVIDER_TIMEZONE = 'America/Los_Angeles'
def dt_string_to_utc_converter(datetime_str)
parsed_dt = parser.parse(datetime_str)
localized_dt = utils.default_tzinfo(parsed_dt, tz.gettz(PROVIDER_TIMEZONE))
utc_dt = localized_dt.astimezone(tz.tzutc())
utc_dt_str = utc_dt.strftime(UTC_TIME_FORMAT)
CodePudding user response:
for the record, here's an option using Python 3.9's zoneinfo and Python 3.7's isoformat.
from datetime import datetime
from zoneinfo import ZoneInfo
def to_isoformat(s, tzname, inputformat='%m/%d/%Y %I:%M %p'):
"""
convert an input string "s" representing date/time in format "inputformat" in
time zone "tzname" to UTC and return an ISO format string with Z denoting UTC.
Parameters
----------
s : str
string representing date/time.
tzname : str
IANA time zone name of time zone that s belongs in.
inputformat : str, optional
date/time string format. The default is '%m/%d/%Y %I:%M %p'.
Returns
-------
str
ISO format string, with seconds precision and Z denoting UTC.
"""
# to datetime and set time zone
dt = datetime.strptime(s, inputformat).replace(tzinfo=ZoneInfo(tzname))
# convert to UTC and make ISO format with Z for UTC
return dt.astimezone(ZoneInfo("UTC")).isoformat(timespec='seconds').replace(' 00:00', 'Z')
print(to_isoformat('01/28/2022 12:00 AM', 'America/Los_Angeles'))
# 2022-01-28T08:00:00Z
With Python 3.8, you can basically just replace from zoneinfo import ZoneInfo with from dateutil.tz import gettz as ZoneInfo.
