I have two inputs time 00:00 and timezone 'Asia/Kolkata'
I want to convert this to UTC time like '18.30'
I don't want to add or subtract offsets because it may affect the day light saving
what i did is
local = pytz.timezone ("UTC")
nativetime = datetime.strptime (setTime,frmt)
local_dt = local.localize(nativetime, is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc)
but this doesn't change anything, the time is not converted to UTC
Please help
Something like this, assuming you're on py3:
>>> import datetime
>>> import pytz
>>> tz = pytz.timezone('Asia/Kolkata')
>>> dt = datetime.datetime(2020, 8, 4, 0, 0, tzinfo=tz)
>>> dt.astimezone(pytz.utc)
datetime.datetime(2020, 8, 3, 18, 7, tzinfo=<UTC>)
>>>
Since you say you're new to Python, it might be good to skip pytz since it's going to be deprecated with Python 3.9. You can use dateutil instead, which can be replaced more easily with zoneinfo in Python 3.9.
from datetime import datetime, timezone
from dateutil.tz import gettz
# assuming you have something like
dt_naive = datetime.strptime('2020-08-05', '%Y-%m-%d')
# dt_naive has no time zone info, so set it:
dt_aware = dt_naive.replace(tzinfo=gettz('Asia/Kolkata'))
# now you can convert to another timezone using .astimezone:
dt_aware_utc = dt_aware.astimezone(timezone.utc)
# datetime.datetime(2020, 8, 4, 18, 30, tzinfo=datetime.timezone.utc)
# -> 5:30 hours behind, which matches dt_aware.utcoffset()
#thebjorn gave me the answer
here is what i did
def utc_to_local(utc_dt,local_tz):
local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz)
return local_tz.normalize(local_dt)
setTime='00:00:00'
setZone='Asia/Kolkata'
datePart = str(datetime.utcnow()).split(' ')[0]
dateTimeUtcStr = datePart+' '+str(setTime)
tz = pytz.timezone('Asia/Kolkata')
tz_utc = pytz.timezone('UTC')
dateTimeRef = datetime.strptime(dateTimeUtcStr, '%Y-%m-%d %H:%M:%S')
#local to utc
tzUtc = pytz.timezone('UTC')
local_dt = tz.localize(dateTimeRef, is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc)
print(utc_dt)
#utc to local
altTime = utc_to_local(utc_dt,tz)
print(altTime)
How do I convert a time to another timezone in Python?
I have found that the best approach is to convert the "moment" of interest to a utc-timezone-aware datetime object (in python, the timezone component is not required for datetime objects).
Then you can use astimezone to convert to the timezone of interest (reference).
from datetime import datetime
import pytz
utcmoment_naive = datetime.utcnow()
utcmoment = utcmoment_naive.replace(tzinfo=pytz.utc)
# print "utcmoment_naive: {0}".format(utcmoment_naive) # python 2
print("utcmoment_naive: {0}".format(utcmoment_naive))
print("utcmoment: {0}".format(utcmoment))
localFormat = "%Y-%m-%d %H:%M:%S"
timezones = ['America/Los_Angeles', 'Europe/Madrid', 'America/Puerto_Rico']
for tz in timezones:
localDatetime = utcmoment.astimezone(pytz.timezone(tz))
print(localDatetime.strftime(localFormat))
# utcmoment_naive: 2017-05-11 17:43:30.802644
# utcmoment: 2017-05-11 17:43:30.802644+00:00
# 2017-05-11 10:43:30
# 2017-05-11 19:43:30
# 2017-05-11 13:43:30
So, with the moment of interest in the local timezone (a time that exists), you convert it to utc like this (reference).
localmoment_naive = datetime.strptime('2013-09-06 14:05:10', localFormat)
localtimezone = pytz.timezone('Australia/Adelaide')
try:
localmoment = localtimezone.localize(localmoment_naive, is_dst=None)
print("Time exists")
utcmoment = localmoment.astimezone(pytz.utc)
except pytz.exceptions.NonExistentTimeError as e:
print("NonExistentTimeError")
Using pytz
from datetime import datetime
from pytz import timezone
fmt = "%Y-%m-%d %H:%M:%S %Z%z"
timezonelist = ['UTC','US/Pacific','Europe/Berlin']
for zone in timezonelist:
now_time = datetime.now(timezone(zone))
print now_time.strftime(fmt)
import datetime
import pytz
def convert_datetime_timezone(dt, tz1, tz2):
tz1 = pytz.timezone(tz1)
tz2 = pytz.timezone(tz2)
dt = datetime.datetime.strptime(dt,"%Y-%m-%d %H:%M:%S")
dt = tz1.localize(dt)
dt = dt.astimezone(tz2)
dt = dt.strftime("%Y-%m-%d %H:%M:%S")
return dt
-
dt: date time string
tz1: initial time zone
tz2: target time zone
-
> convert_datetime_timezone("2017-05-13 14:56:32", "Europe/Berlin", "PST8PDT")
'2017-05-13 05:56:32'
> convert_datetime_timezone("2017-05-13 14:56:32", "Europe/Berlin", "UTC")
'2017-05-13 12:56:32'
-
> pytz.all_timezones[0:10]
['Africa/Abidjan',
'Africa/Accra',
'Africa/Addis_Ababa',
'Africa/Algiers',
'Africa/Asmara',
'Africa/Asmera',
'Africa/Bamako',
'Africa/Bangui',
'Africa/Banjul',
'Africa/Bissau']
Python 3.9 adds the zoneinfo module so now only the the standard library is needed!
>>> from zoneinfo import ZoneInfo
>>> from datetime import datetime
>>> d = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo('America/Los_Angeles'))
>>> d.astimezone(ZoneInfo('Europe/Berlin')) # 12:00 in Cali will be 20:00 in Berlin
datetime.datetime(2020, 10, 31, 20, 0, tzinfo=zoneinfo.ZoneInfo(key='Europe/Berlin'))
Wikipedia list of available time zones
Some functions such as now() and utcnow() return timezone-unaware datetimes, meaning they contain no timezone information. I recommend only requesting timezone-aware values from them using the keyword tz=ZoneInfo('localtime').
If astimezone gets a timezone-unaware input, it will assume it is local time, which can lead to errors:
>>> datetime.utcnow() # UTC -- NOT timezone-aware!!
datetime.datetime(2020, 6, 1, 22, 39, 57, 376479)
>>> datetime.now() # Local time -- NOT timezone-aware!!
datetime.datetime(2020, 6, 2, 0, 39, 57, 376675)
>>> datetime.now(tz=ZoneInfo('localtime')) # timezone-aware
datetime.datetime(2020, 6, 2, 0, 39, 57, 376806, tzinfo=zoneinfo.ZoneInfo(key='localtime'))
>>> datetime.now(tz=ZoneInfo('Europe/Berlin')) # timezone-aware
datetime.datetime(2020, 6, 2, 0, 39, 57, 376937, tzinfo=zoneinfo.ZoneInfo(key='Europe/Berlin'))
>>> datetime.utcnow().astimezone(ZoneInfo('Europe/Berlin')) # WRONG!!
datetime.datetime(2020, 6, 1, 22, 39, 57, 377562, tzinfo=zoneinfo.ZoneInfo(key='Europe/Berlin'))
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
Time conversion
To convert a time in one timezone to another timezone in Python, you could use datetime.astimezone():
so, below code is to convert the local time to other time zone.
datetime.datetime.today() - return current the local time
datetime.astimezone() - convert the time zone, but we have to pass the time zone.
pytz.timezone('Asia/Kolkata') -passing the time zone to pytz module
Strftime - Convert Datetime to string
# Time conversion from local time
import datetime
import pytz
dt_today = datetime.datetime.today() # Local time
dt_India = dt_today.astimezone(pytz.timezone('Asia/Kolkata'))
dt_London = dt_today.astimezone(pytz.timezone('Europe/London'))
India = (dt_India.strftime('%m/%d/%Y %H:%M'))
London = (dt_London.strftime('%m/%d/%Y %H:%M'))
print("Indian standard time: "+India+" IST")
print("British Summer Time: "+London+" BST")
List all the time zones
import pytz
for tz in pytz.all_timezones:
print(tz)
To convert a time in one timezone to another timezone in Python, you could use datetime.astimezone():
time_in_new_timezone = time_in_old_timezone.astimezone(new_timezone)
Given aware_dt (a datetime object in some timezone), to convert it to other timezones and to print the times in a given time format:
#!/usr/bin/env python3
import pytz # $ pip install pytz
time_format = "%Y-%m-%d %H:%M:%S%z"
tzids = ['Asia/Shanghai', 'Europe/London', 'America/New_York']
for tz in map(pytz.timezone, tzids):
time_in_tz = aware_dt.astimezone(tz)
print(f"{time_in_tz:{time_format}}")
If f"" syntax is unavailable, you could replace it with "".format(**vars())
where you could set aware_dt from the current time in the local timezone:
from datetime import datetime
import tzlocal # $ pip install tzlocal
local_timezone = tzlocal.get_localzone()
aware_dt = datetime.now(local_timezone) # the current time
Or from the input time string in the local timezone:
naive_dt = datetime.strptime(time_string, time_format)
aware_dt = local_timezone.localize(naive_dt, is_dst=None)
where time_string could look like: '2016-11-19 02:21:42'. It corresponds to time_format = '%Y-%m-%d %H:%M:%S'.
is_dst=None forces an exception if the input time string corresponds to a non-existing or ambiguous local time such as during a DST transition. You could also pass is_dst=False, is_dst=True. See links with more details at Python: How do you convert datetime/timestamp from one timezone to another timezone?
For Python timezone conversions, I use the handy table from the PyCon 2012 presentation by Taavi Burns.
Please note: The first part of this answer is or version 1.x of pendulum. See below for a version 2.x answer.
I hope I'm not too late!
The pendulum library excels at this and other date-time calculations.
>>> import pendulum
>>> some_time_zones = ['Europe/Paris', 'Europe/Moscow', 'America/Toronto', 'UTC', 'Canada/Pacific', 'Asia/Macao']
>>> heres_a_time = '1996-03-25 12:03 -0400'
>>> pendulum_time = pendulum.datetime.strptime(heres_a_time, '%Y-%m-%d %H:%M %z')
>>> for tz in some_time_zones:
... tz, pendulum_time.astimezone(tz)
...
('Europe/Paris', <Pendulum [1996-03-25T17:03:00+01:00]>)
('Europe/Moscow', <Pendulum [1996-03-25T19:03:00+03:00]>)
('America/Toronto', <Pendulum [1996-03-25T11:03:00-05:00]>)
('UTC', <Pendulum [1996-03-25T16:03:00+00:00]>)
('Canada/Pacific', <Pendulum [1996-03-25T08:03:00-08:00]>)
('Asia/Macao', <Pendulum [1996-03-26T00:03:00+08:00]>)
Answer lists the names of the time zones that may be used with pendulum. (They're the same as for pytz.)
For version 2:
some_time_zones is a list of the names of the time zones that might be used in a program
heres_a_time is a sample time, complete with a time zone in the form '-0400'
I begin by converting the time to a pendulum time for subsequent processing
now I can show what this time is in each of the time zones in show_time_zones
...
>>> import pendulum
>>> some_time_zones = ['Europe/Paris', 'Europe/Moscow', 'America/Toronto', 'UTC', 'Canada/Pacific', 'Asia/Macao']
>>> heres_a_time = '1996-03-25 12:03 -0400'
>>> pendulum_time = pendulum.from_format('1996-03-25 12:03 -0400', 'YYYY-MM-DD hh:mm ZZ')
>>> for tz in some_time_zones:
... tz, pendulum_time.in_tz(tz)
...
('Europe/Paris', DateTime(1996, 3, 25, 17, 3, 0, tzinfo=Timezone('Europe/Paris')))
('Europe/Moscow', DateTime(1996, 3, 25, 19, 3, 0, tzinfo=Timezone('Europe/Moscow')))
('America/Toronto', DateTime(1996, 3, 25, 11, 3, 0, tzinfo=Timezone('America/Toronto')))
('UTC', DateTime(1996, 3, 25, 16, 3, 0, tzinfo=Timezone('UTC')))
('Canada/Pacific', DateTime(1996, 3, 25, 8, 3, 0, tzinfo=Timezone('Canada/Pacific')))
('Asia/Macao', DateTime(1996, 3, 26, 0, 3, 0, tzinfo=Timezone('Asia/Macao')))
For Python 3.2+ simple-date is a wrapper around pytz that tries to simplify things.
If you have a time then
SimpleDate(time).convert(tz="...")
may do what you want. But timezones are quite complex things, so it can get significantly more complicated - see the the docs.
# Program
import time
import os
os.environ['TZ'] = 'US/Eastern'
time.tzset()
print('US/Eastern in string form:',time.asctime())
os.environ['TZ'] = 'Australia/Melbourne'
time.tzset()
print('Australia/Melbourne in string form:',time.asctime())
os.environ['TZ'] = 'Asia/Kolkata'
time.tzset()
print('Asia/Kolkata in string form:',time.asctime())
I get the server date and I need to get the difference of this date from GMT
I get
Datetime = "2011-04-27 2:17:45"
I would like to get the result like
Datetime = "2011-04-27 2:17:45 +0500"
Try this:
import datetime, pytz
now = datetime.datetime.now(pytz.timezone('Asia/Kolkata'))
print now.strftime('%Y-%m-%d %H:%M:%S %z')
# prints: '2011-04-27 13:56:09 +0530'
From the example you have given, it looks to me that what you are looking for is datetime.isoformat. The example in the page shows how to convert the datetime values to the ISO format with the time zone information.
To do this, you have to know the timezone (or the UTC offset) of the server date. What you have here is a "naive" date, without timezone info, you can't guess the UTC difference.
I think the datetime module is what you need here:
>>> from datetime import datetime
>>> datetime.now()
datetime.datetime(2011, 4, 27, 11, 8, 26, 149000)
>>> datetime.utcnow()
datetime.datetime(2011, 4, 27, 8, 8, 47, 712000)
For a difference between two dates:
>>> dtnow = datetime.now()
>>> dtutc = datetime.utcnow()
>>> dtnow - dtutc
datetime.timedelta(0, 10792, 847000)
Look up the datetime module and the relevant classes in Python's docs.
A very powerful extension of the datetime standard python library is the dateutil one, that allows you to easily:
set the delta of your time zone:
parse dates with various convenient options (in our case we will use the default option, which will allow us to set our time zone)
So 1st set time zone, and default date with this zone:
>>> from datetime import datetime
>>> from dateutil import parser
>>> from dateutil.tz import tzoffset
>>> tz_plus_5 = tzoffset(None, 5 * 60 * 60) # offset is in seconds !
>>> default = datetime.now(tz_plus_5)
Now use this default date in the parsing:
>>> Datetime = "2011-04-27 2:17:45"
>>> my_date = parser.parse(Datetime, default=default)
>>> my_date
datetime.datetime(2011, 4, 27, 2, 17, 45, tzinfo=tzoffset(None, 18000))
>>> my_date.strftime("%Y-%m-%d %H:%M:%S %z")
'2011-04-27 02:17:45 +0500'
For those that simply need to get the offset between local time and UTC, the time module has an attribute time.altzone that specifies the difference between UTC and local time in seconds:
The offset of the local DST timezone, in seconds west of UTC, if one is defined. This is negative if the local DST timezone is east of UTC (as in Western Europe, including the UK). Only use this if daylight is nonzero.
Here's an example of how it works:
>>> datetime.now().isoformat()
'2011-09-01T17:26:46.971000'
>>> datetime.utcnow().isoformat()
'2011-09-01T15:27:32.699000'
>>> time.altzone / (60*60)
-2
Doesn't get much cleaner than that.
Suppose I have date d like this :
>>> d
datetime(2009, 4, 19, 21, 12, tzinfo=tzoffset(None, -7200))
As you can see, it is "timezone aware", there is an offset of 2 Hour, utctime is
>>> d.utctimetuple()
time.struct_time(tm_year=2009, tm_mon=4, tm_mday=19,
tm_hour=23, tm_min=12, tm_sec=0,
tm_wday=6, tm_yday=109, tm_isdst=0)
So, real UTC date is 19th March 2009 23:12:00, right ?
Now I need to format my date in string, I use
>>> d.strftime('%Y-%m-%d %H:%M:%S.%f')
'2009-04-19 21:12:00.000000'
Which doesn't seems to take this offset into account. How to fix that ?
In addition to what #Slam has already answered:
If you want to output the UTC time without any offset, you can do
from datetime import timezone, datetime, timedelta
d = datetime(2009, 4, 19, 21, 12, tzinfo=timezone(timedelta(hours=-2)))
d.astimezone(timezone.utc).strftime('%Y-%m-%d %H:%M:%S.%f')
See datetime.astimezone in the Python docs.
The reason is python actually formatting your datetime object, not some "UTC at this point of time"
To show timezone in formatting, use %z or %Z.
Look for strf docs for details
This will convert your local time to UTC and print it:
import datetime, pytz
from dateutil.tz.tz import tzoffset
loc = datetime.datetime(2009, 4, 19, 21, 12, tzinfo=tzoffset(None, -7200))
print(loc.astimezone(pytz.utc).strftime('%Y-%m-%d %H:%M:%S.%f') )
(http://pytz.sourceforge.net/)
I couldn't import timezone module (and hadn't much time to know why)
so I set TZ environment variable which override the /etc/localtime information
>>> import os
>>> import datetime
>>> print datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
2019-05-17 11:26
>>> os.environ["TZ"] = "UTC"
>>> print datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
2019-05-17 09:26