How to convert a UTC datetime to a local datetime using only standard library? How to convert a UTC datetime to a local datetime using only standard library? python python

How to convert a UTC datetime to a local datetime using only standard library?


In Python 3.3+:

from datetime import datetime, timezonedef utc_to_local(utc_dt):    return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)

In Python 2/3:

import calendarfrom datetime import datetime, timedeltadef utc_to_local(utc_dt):    # get integer timestamp to avoid precision lost    timestamp = calendar.timegm(utc_dt.timetuple())    local_dt = datetime.fromtimestamp(timestamp)    assert utc_dt.resolution >= timedelta(microseconds=1)    return local_dt.replace(microsecond=utc_dt.microsecond)

Using pytz (both Python 2/3):

import pytzlocal_tz = pytz.timezone('Europe/Moscow') # use your local timezone name here# NOTE: pytz.reference.LocalTimezone() would produce wrong result here## You could use `tzlocal` module to get local timezone on Unix and Win32# from tzlocal import get_localzone # $ pip install tzlocal# # get local timezone    # local_tz = get_localzone()def utc_to_local(utc_dt):    local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz)    return local_tz.normalize(local_dt) # .normalize might be unnecessary

Example

def aslocaltimestr(utc_dt):    return utc_to_local(utc_dt).strftime('%Y-%m-%d %H:%M:%S.%f %Z%z')print(aslocaltimestr(datetime(2010,  6, 6, 17, 29, 7, 730000)))print(aslocaltimestr(datetime(2010, 12, 6, 17, 29, 7, 730000)))print(aslocaltimestr(datetime.utcnow()))

Output

Python 3.3
2010-06-06 21:29:07.730000 MSD+04002010-12-06 20:29:07.730000 MSK+03002012-11-08 14:19:50.093745 MSK+0400
Python 2
2010-06-06 21:29:07.730000 2010-12-06 20:29:07.730000 2012-11-08 14:19:50.093911 
pytz
2010-06-06 21:29:07.730000 MSD+04002010-12-06 20:29:07.730000 MSK+03002012-11-08 14:19:50.146917 MSK+0400

Note: it takes into account DST and the recent change of utc offset for MSK timezone.

I don't know whether non-pytz solutions work on Windows.


Since Python 3.9 you can use the zoneinfo module.

First lets get that time with utcnow():

>>> from datetime import datetime>>> database_time = datetime.utcnow()>>> database_timedatetime.datetime(2021, 9, 24, 4, 18, 27, 706532)

Then create the time zones:

>>> from zoneinfo import ZoneInfo>>> utc = ZoneInfo('UTC')>>> localtz = ZoneInfo('localtime')

Then convert. To convert between timezones, the datetime must know what timezone it is in, then we just use astimezone():

>>> utctime = database_time.replace(tzinfo=utc)>>> localtime = utctime.astimezone(localtz)>>> localtimedatetime.datetime(2021, 9, 24, 6, 18, 27, 706532, tzinfo=zoneinfo.ZoneInfo(key='localtime'))

For Python 3.6 to 3.8 you need the backports.zoneinfo module:

>>> try:>>>     from zoneinfo import ZoneInfo>>> except ImportError:>>>     from backports.zoneinfo import ZoneInfo

The rest is the same.

For versions earlier than that need pytz or dateutil. datutil works similar to zoneinfo:

>>> from dateutil import tz>>> utc = tz.gettz('UTC')>>> localtz = tz.tzlocal()The Conversion:>>> utctime = now.replace(tzinfo=UTC)>>> localtime = utctime.astimezone(localtz)>>> localtimedatetime.datetime(2010, 12, 30, 15, 51, 22, 114668, tzinfo=tzlocal())

pytz has a different interface which is a result of Python's time zone handling not handling ambigous times:

>>> import pytz>>> utc = pytz.timezone('UTC')# There is no local timezone support, you need to know your timezone>>> localtz = pytz.timezone('Europe/Paris')>>> utctime = utc.localize(database_time)>>> localtime = localtz.normalize(utctime.astimezone(localtz))>>> localtime


Python 3.9 adds the zoneinfo module so now it can be done as follows (stdlib only):

from zoneinfo import ZoneInfofrom datetime import datetimeutc_unaware = datetime(2020, 10, 31, 12)  # loaded from databaseutc_aware = utc_unaware.replace(tzinfo=ZoneInfo('UTC'))  # make awarelocal_aware = utc_aware.astimezone(ZoneInfo('localtime'))  # convert

Central Europe is 1 or 2 hours ahead of UTC, so local_aware is:

datetime.datetime(2020, 10, 31, 13, 0, tzinfo=backports.zoneinfo.ZoneInfo(key='localtime'))

as str:

2020-10-31 13:00:00+01:00

Windows has no system time zone database, so here an extra package is needed:

pip install tzdata  

There is a backport to allow use in Python 3.6 to 3.8:

sudo pip install backports.zoneinfo

Then:

from backports.zoneinfo import ZoneInfo