How to convert a UTC datetime to a local datetime using only standard library?
--
Track title: CC B Schuberts Piano Sonata No 16 D
--
Chapters
00:00 Question
00:53 Accepted answer (Score 6)
01:34 Answer 2 (Score 419)
03:01 Answer 3 (Score 79)
04:35 Answer 4 (Score 26)
05:38 Thank you
--
Full question
https://stackoverflow.com/questions/4563...
Answer 2 links:
[pytz]: http://pypi.python.org/pypi/pytz
[dateutil]: http://pypi.python.org/pypi/python-dateu...
Answer 3 links:
[zoneinfo]: https://docs.python.org/3.9/library/zone...
[has no]: https://docs.python.org/3.9/library/zone...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #datetime #timezone #pythondatetime
#avk47
ANSWER 1
Score 448
In Python 3.3+:
from datetime import datetime, timezone
def utc_to_local(utc_dt):
return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)
In Python 2/3:
import calendar
from datetime import datetime, timedelta
def 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 pytz
local_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.32010-06-06 21:29:07.730000 MSD+0400
2010-12-06 20:29:07.730000 MSK+0300
2012-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+0400
2010-12-06 20:29:07.730000 MSK+0300
2012-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.
ANSWER 2
Score 99
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_time
datetime.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)
>>> localtime
datetime.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)
>>> localtime
datetime.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
ANSWER 3
Score 17
You can't do it with standard library. Using pytz module you can convert any naive/aware datetime object to any other time zone. Lets see some examples using Python 3.
Naive objects created through class method
utcnow()
To convert a naive object to any other time zone, first you have to convert it into aware datetime object. You can use the replace method for converting a naive datetime object to an aware datetime object. Then to convert an aware datetime object to any other timezone you can use astimezone method.
The variable pytz.all_timezones gives you the list of all available time zones in pytz module.
import datetime,pytz
dtobj1=datetime.datetime.utcnow() #utcnow class method
print(dtobj1)
dtobj3=dtobj1.replace(tzinfo=pytz.UTC) #replace method
dtobj_hongkong=dtobj3.astimezone(pytz.timezone("Asia/Hong_Kong")) #astimezone method
print(dtobj_hongkong)
Naive objects created through class method
now()
Because now method returns current date and time, so you have to make the datetime object timezone aware first. The localize function converts a naive datetime object into a timezone-aware datetime object. Then you can use the astimezone method to convert it into another timezone.
dtobj2=datetime.datetime.now()
mytimezone=pytz.timezone("Europe/Vienna") #my current timezone
dtobj4=mytimezone.localize(dtobj2) #localize function
dtobj_hongkong=dtobj4.astimezone(pytz.timezone("Asia/Hong_Kong")) #astimezone method
print(dtobj_hongkong)
ANSWER 4
Score 8
Building on Alexei's comment. This should work for DST too.
import time
import datetime
def utc_to_local(dt):
if time.localtime().tm_isdst:
return dt - datetime.timedelta(seconds = time.altzone)
else:
return dt - datetime.timedelta(seconds = time.timezone)