Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a python datetime instance that was created using datetime.utcnow() and persisted in database.

For display, I would like to convert the datetime instance retrieved from the database to local datetime using the default local timezone (i.e., as if the datetime was created using datetime.now()).

How can I convert the UTC datetime to a local datetime using only python standard library (e.g., no pytz dependency)?

It seems one solution would be to use datetime.astimezone(tz), but how would you get the default local timezone?

like image 664
Nitro Zark Avatar asked Oct 18 '22 07:10

Nitro Zark


People also ask

How do you convert UTC time to local time?

Add the local time offset to the UTC time. For example, if your local time offset is -5:00, and if the UTC time is shown as 11:00, add -5 to 11. The time setting when adjusted for offset is 06:00 (6:00 A.M.).

How do you convert UTC to local time in Python?

This datetime object will have no timezone associated with it. Therefore assign the UTC timezone to this datetime object using replace(tzinfo=pytz. UTC) function. Convert the timezone of the datetime object to local timezone by calling the astimezone() function on datetime object.

How do you convert UTC time to local time in node JS?

Use the Date() constructor to convert UTC to local time, e.g. new Date(utcDateStr) . Passing a date and time string in ISO 8601 format to the Date() constructor converts the UTC date and time to local time. Copied!

How do I change the timezone on a datetime object?

The correct way is to use timezone. localize() instead. Using datetime. replace() is OK when working with UTC as shown above because it does not have daylight savings time transitions to deal with.


1 Answers

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.3
2010-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.

like image 408
jfs Avatar answered Oct 19 '22 19:10

jfs