How to convert a UTC datetime to a local datetime using only standard library?
I think I figured it out: computes number of seconds since epoch, then converts to a local timzeone using time.localtime, and then converts the time struct back into a datetime...
EPOCH_DATETIME = datetime.datetime(1970,1,1)
SECONDS_PER_DAY = 24*60*60
def utc_to_local_datetime( utc_datetime ):
delta = utc_datetime - EPOCH_DATETIME
utc_epoch = SECONDS_PER_DAY * delta.days + delta.seconds
time_struct = time.localtime( utc_epoch )
dt_args = time_struct[:6] + (delta.microseconds,)
return datetime.datetime( *dt_args )
It applies the summer/winter DST correctly:
>>> utc_to_local_datetime( datetime.datetime(2010, 6, 6, 17, 29, 7, 730000) )
datetime.datetime(2010, 6, 6, 19, 29, 7, 730000)
>>> utc_to_local_datetime( datetime.datetime(2010, 12, 6, 17, 29, 7, 730000) )
datetime.datetime(2010, 12, 6, 18, 29, 7, 730000)
Python (datetime) timezone conversion off by 4 minutes
From pytz documentation:
This library differs from the documented Python API for tzinfo implementations; if you want to create local wallclock times you need to use the
localize()
method documented in this document. In addition, if you perform date arithmetic on local times that cross DST boundaries, the result may be in an incorrect timezone (ie. subtract 1 minute from 2002-10-27 1:00 EST and you get 2002-10-27 0:59 EST instead of the correct 2002-10-27 1:59 EDT).
So, you are using pytz incorrectly.
Following is both correct, and erroneous code Following code shows results of your use of pytz (datetime.replace(tzinfo=pytz.timezone)
), and the recommended way of using pytz with datetime (pytz.timezone.localize(datetime)
).
from datetime import datetime, date, time, timezone
from dateutil import tz
import pytz
d = date(2019, 1, 27)
t = time(19, 32, 00)
t1 = datetime.combine(d, t)
t1_epoch = t1.timestamp()
print("t1_epoch " + str(t1_epoch))
print("t1 " + str(t1))
# your approach/code
nytz = pytz.timezone('America/New_York')
t3 = t1.replace(tzinfo=nytz)
t3_epoch = t3.timestamp()
print("t3_epoch " + str(t3_epoch))
print("t3 " + str(t3))
# recommended approach/code using localize
nytz = pytz.timezone('America/New_York')
t6 = nytz.localize(t1)
t6_epoch = t6.timestamp()
print("t6_epoch " + str(t6_epoch))
print("t6 " + str(t6))
Output of above code:
t1_epoch 1548617520.0
t1 2019-01-27 19:32:00
t3_epoch 1548635280.0
t3 2019-01-27 19:32:00-04:56
t6_epoch 1548635520.0
t6 2019-01-27 19:32:00-05:00
t3
is what you are doing, and it is giving incorrect offset (-4:56). Note that POSIX time is also incorrect in this case. POSIX time, by definition, does not change with timezone.
t6
has been created using pytz.timezone.localize()
method, and gives correct UTC offset (-5:00).
Update: Updated language of the answer as one user found the answer confusing.
How do you convert a datetime/timestamp from one timezone to another timezone?
If you know your origin timezone and the new timezone that you want to convert it to, it turns out to be very straightforward:
Make two
pytz.timezone
objects, one for the current timezone and one for the new timezone e.g.pytz.timezone("US/Pacific")
. You can find a list of all official timezones inpytz
library:import pytz; pytz.all_timezones
Localize the datetime/timestamp of interest to the current timezone e.g.
current_timezone = pytz.timezone("US/Eastern")
localized_timestamp = current_timezone.localize(timestamp)
- Convert to new timezone using
.astimezone()
on the newly localized datetime/timestamp from step 2 with the desired timezone's pytz object as input e.g.localized_timestamp.astimezone(new_timezone)
.
Done!
As a full example:
import datetime
import pytz
# a timestamp I'd like to convert
my_timestamp = datetime.datetime.now()
# create both timezone objects
old_timezone = pytz.timezone("US/Eastern")
new_timezone = pytz.timezone("US/Pacific")
# two-step process
localized_timestamp = old_timezone.localize(my_timestamp)
new_timezone_timestamp = localized_timestamp.astimezone(new_timezone)
# or alternatively, as an one-liner
new_timezone_timestamp = old_timezone.localize(my_timestamp).astimezone(new_timezone)
Bonus: but if all you need is the current time in a specific timezone, you can conveniently pass that timezone directly into datetime.now() to get the current times directly:
datetime.datetime.now(new_timezone)
When it comes to needing timezones conversions generally, I would strongly advise that one should store all timestamps in your database in UTC, which has no daylight savings time (DST) transition. And as a good practice, one should always choose to enable time zone support (even if your users are all in a single time zone!). This will help you avoid the DST transition problem that plagues so much software today.
Beyond DST, time in software can be generally quite tricky. To get a sense of just how difficult it is to deal with time in software in general, here is a potentially enlightening resource: http://yourcalendricalfallacyis.com
Even a seemingly simple operation as converting a datetime/timestamp into a date can become non-obvious. As this helpful documentation points out:
A datetime represents a point in time. It’s absolute: it doesn’t depend on anything. On the contrary, a date is a calendaring concept. It’s a period of time whose bounds depend on the time zone in which the date is considered. As you can see, these two concepts are fundamentally different.
Understanding this difference is a key step towards avoiding time-based bugs. Good luck.
Conversion of timezone of datetime.time
add an appropriate date to the input string and this works as you expect:
import arrow
start = '2021-02-01 18:30+0000'
start_time = arrow.get(start)
print(start_time.to('Australia/Melbourne').format('hh:mm A ZZ'))
# 05:30 AM +11:00
Python time zone conversion from UTC to EST
you need to set UTC first, then convert to the desired tz:
from datetime import datetime, timezone
from zoneinfo import ZoneInfo # Python 3.9+ standard lib
l = [['File_1','2021-09-09 07:05:10'],['File_2','2021-09-08 08:05:11']]
out = [[i[0], datetime.fromisoformat(i[1]) # Python 3.7+
.replace(tzinfo=timezone.utc)
.astimezone(ZoneInfo("America/New_York"))] for i in l]
print(out)
# [['File_1', datetime.datetime(2021, 9, 9, 3, 5, 10, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))], ['File_2', datetime.datetime(2021, 9, 8, 4, 5, 11, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))]]
# with pytz:
import pytz
outp = [[i[0], datetime.fromisoformat(i[1]) # Python 3.7+
.replace(tzinfo=timezone.utc)
.astimezone(pytz.timezone("America/New_York"))] for i in l]
print(outp)
# [['File_1', datetime.datetime(2021, 9, 9, 3, 5, 10, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)], ['File_2', datetime.datetime(2021, 9, 8, 4, 5, 11, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)]]
If you want a string instead of datetime object, use strftime or even simpler: .isoformat().
Python: Convert local time to another time zone
You can use the datetime
module instead. Adapted from http://docs.python.org/library/datetime.html#datetime.tzinfo.fromutc
from datetime import tzinfo, timedelta, datetime
class FixedOffset(tzinfo):
def __init__(self, offset):
self.__offset = timedelta(hours=offset)
self.__dst = timedelta(hours=offset-1)
self.__name = ''
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return self.__dst
print datetime.now()
print datetime.now(FixedOffset(9))
Gives:
2011-03-12 00:28:32.214000
2011-03-12 14:28:32.215000+09:00
When I run it (I'm UTC-0500 for another day, then DST begins)
How to convert local time string to UTC?
Thanks @rofly, the full conversion from string to string is as follows:
time.strftime("%Y-%m-%d %H:%M:%S",
time.gmtime(time.mktime(time.strptime("2008-09-17 14:04:00",
"%Y-%m-%d %H:%M:%S"))))
My summary of the time
/calendar
functions:
time.strptime
string --> tuple (no timezone applied, so matches string)
time.mktime
local time tuple --> seconds since epoch (always local time)
time.gmtime
seconds since epoch --> tuple in UTC
and
calendar.timegm
tuple in UTC --> seconds since epoch
time.localtime
seconds since epoch --> tuple in local timezone
Related Topics
How to Use a Dll File from Python
Rotate Axis Text in Python Matplotlib
Compare Object Instances for Equality by Their Attributes
How to Check If All Elements of a List Match a Condition
How to Send a Head Http Request in Python 2
Activate a Virtualenv with a Python Script
How to Hide Console Window in Python
Generating Permutations with Repetitions
In Pandas, Is Inplace = True Considered Harmful, or Not
Using Lambda Expression to Connect Slots in Pyqt
Create Pandas Dataframe from Txt File with Specific Pattern
Python Analog of PHP's Natsort Function (Sort a List Using a "Natural Order" Algorithm)
From ... Import' VS 'Import .'
Setup Script Exited with Error: Command 'X86_64-Linux-Gnu-Gcc' Failed with Exit Status 1