Handling timezone in Python
UTC, or Coordinated Universal Time, is the primary time standard by which the world regulates date and time.
astimezone()
–> it helps to convert the time of a particular time zone into another time zonelocaltime()
–> it helps to get the current local time
import pytz
from datetime import datetime
print('The supported tz:', pytz.all_timezones, '\n')
Get country datetime
- Show date-time for different timezone/country
datetime_ist = datetime.now(pytz.timezone('Asia/Kolkata'))
print("IST: ", datetime_ist.strftime("%m/%d/%Y, %H:%M:%S"))
# IST: 07/28/2021, 15:19:41
# UTC time --> IST-5.30
datetime_utc = datetime.now(pytz.timezone('UTC'))
# datetime_utc = datetime.now(timezone.utc) # Alt way
print("UTC: ", datetime_utc.strftime("%m/%d/%Y, %H:%M:%S"))
# UTC: 07/28/2021, 09:49:41
# current date and time of NY
datetime_NY = datetime.now(pytz.timezone('America/New_York'))
print("NY:", datetime_NY.strftime("%m/%d/%Y, %H:%M:%S"))
# NY: 07/28/2021, 05:49:41
# current date and time of London
datetime_London = datetime.now(pytz.timezone('Europe/London'))
print("London:", datetime_London.strftime("%m/%d/%Y, %H:%M:%S"))
# London: 07/28/2021, 10:49:41
Timezone Conversion
- format: old_tz_time.astimezone(new_tz)
Any timezone to UTC
datetime_NY = datetime.now(pytz.timezone('America/New_York'))
NY_to_utc = datetime_NY.astimezone(pytz.utc)
print("NY_to_utc: ", NY_to_utc.strftime("%m/%d/%Y, %H:%M:%S"))
# NY_to_utc: 07/28/2021, 09:49:41
datetime_ist = datetime.now(pytz.timezone('Asia/Kolkata'))
ist_to_utc = datetime_ist.astimezone(pytz.utc)
print("IST_to_utc: ", ist_to_utc.strftime("%m/%d/%Y, %H:%M:%S"))
# IST_to_utc: 07/28/2021, 09:49:41
UTC to any timezone
UTC_to_ist = datetime_utc.astimezone(pytz.timezone('Asia/Kolkata'))
print("UTC_to_ist: ",UTC_to_ist.strftime("%m/%d/%Y, %H:%M:%S"))
# UTC_to_ist: 07/28/2021, 15:19:41
Any to any timezone
datetime_NY = datetime.now(pytz.timezone('America/New_York'))
NY_to_London = datetime_NY.astimezone(pytz.timezone('Europe/London'))
print("NY_to_London:", NY_to_London.strftime("%m/%d/%Y, %H:%M:%S"))
# NY_to_London: 07/28/2021, 10:49:41
Timezone unaware/naive to Timezone aware
localize()
–> Works on Naiveastimezone()
–> Works on both Naive and Awarereplace()
# India naive to aware
ist = pytz.timezone('Asia/Kolkata')
naive_india = datetime.now()
# datetime.datetime(2021, 7, 28, 16, 56, 20, 516114)
aware_india_localize = ist.localize(naive_india)
# datetime.datetime(2021, 7, 28, 16, 56, 20, 516114, tzinfo=<DstTzInfo 'Asia/Kolkata' IST+5:30:00 STD>)
aware_india_astimezone = naive_india.astimezone(ist)
# datetime.datetime(2021, 7, 28, 16, 56, 20, 516114, tzinfo=<DstTzInfo 'Asia/Kolkata' IST+5:30:00 STD>)
# with replace()
aware_india_replace = naive_india.replace(tzinfo=ist)
# datetime.datetime(2021, 7, 28, 16, 56, 20, 516114, tzinfo=<DstTzInfo 'Asia/Kolkata' LMT+5:53:00 STD>)
# Naive to UTC
datetime.now()
# datetime.datetime(2022, 1, 20, 10, 27, 13, 264799)
pz_utc = pytz.timezone('utc')
pz_utc.localize(datetime.now())
# datetime.datetime(2022, 1, 20, 10, 27, 11, 91797, tzinfo=<UTC>)
pz_utc.localize(datetime(year=2022, month=1, day=14, hour=1, minute=0))
# datetime.datetime(2022, 1, 14, 1, 0, tzinfo=<UTC>)
Issue with replace
naive_india.replace(tzinfo=ist).astimezone(pytz.utc)
# datetime.datetime(2021, 7, 28, 11, 3, 20, 516114, tzinfo=<UTC>)
aware_india_localize.astimezone(pytz.utc)
# datetime.datetime(2021, 7, 28, 11, 26, 20, 516114, tzinfo=<UTC>)
print(ist)
# <DstTzInfo 'Asia/Kolkata' LMT+5:53:00 STD>
NOTE:
- If you look carefully, the information about ist is
LMT+5:53:00 STD
- Which you might think is incorrect as the offset of IST from
UTC is +5:30 and not 5:53
- Initially IST was declared to be +5:53 ahead of UTC which was corrected later on to be +5:30.
- But replace doesn’t really know about this
- If you look carefully, the information about ist is
# Newer time
pytz.timezone('Asia/Kolkata').localize(datetime.now())
# datetime.datetime(2021, 7, 28, 17, 32, 48, 491126, tzinfo=<DstTzInfo 'Asia/Kolkata' IST+5:30:00 STD>)
# Old time
pytz.timezone('Asia/Kolkata').localize(datetime(1700,1,1))
# datetime.datetime(1700, 1, 1, 0, 0, tzinfo=<DstTzInfo 'Asia/Kolkata' LMT+5:53:00 STD>)
- You can see the correct offset this time.
- Whereas, for old_days, when localized to IST, the offset is 5:53.
- Depending on the time, it returns the offset accordingly.
- +5:53 for a really old date and +5:30 for a date after the time that the offset for IST was corrected.
Get Timezone info
from pytz import tzinfo
print(aware_india.tzinfo) # Asia/Kolkata
print(naive_india.tzinfo) # None
Gyan
Dos
- Always use aware datetime objects.
- When dealing with naive objects, use localize to add timezone
- When you are converting timezones use astimezone.
Don’t
- Create naive datetime objects.
- Use datetime.datetime.replace for adding or manipulating timezone information on a datetime object.
- Except when you use it to instantiate a datetime object in UTC.