Home > Blockchain >  Convert timezone naive datetime string to UTC datetime (but not using pytz)
Convert timezone naive datetime string to UTC datetime (but not using pytz)

Time:02-01

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.

  •  Tags:  
  • Related