Handling timezones in Python (datetime, pytz)

I found it difficult to understand how to handle time zones in Python, so this is an organized memo.

version information

datetime class

There are the following two types of instances in the same class.

Aware and Naive Objects - datetime — Basic date and time types — Python 3.8.1rc1 documentation

How to get the current time

from datetime import datetime
from datetime import timezone

now = datetime.now()
print(now) # =>Now in Japan time
print(now.tzinfo) # => None
# Naive

now = datetime.utcnow()
print(now) # =>Time minus 9 hours from Japan time
print(now.tzinfo) # => None
# Naive

now = datetime.now(timezone.utc)
print(now) #At the time minus 9 hours"+00:00"With the notation
print(now.tzinfo) # => UTC
# Aware

How to get an instance of datetime from Unixtime

from datetime import datetime
from datetime import timezone

unixtime = 1572764400

now = datetime.fromtimestamp(unixtime)
print(now) # =>Notation in Japan time of the moment represented by unix time
print(now.tzinfo) # => None
# Naive

now = datetime.utcfromtimestamp(unixtime)
print(now) #Time minus 9 hours=UTC notation of the moment represented by unix time
print(now.tzinfo) # => None
# Naive

now = datetime.fromtimestamp(unixtime, timezone.utc)
print(now) #At the time minus 9 hours"+00:00"With the notation
print(now.tzinfo)
# => UTC
# Aware

A quick way to shift 9 hours without saying difficult things

from datetime import datetime
from datetime import timedelta

now = datetime.now() # Naive
print(now) # =>Now in Japan time(No time zone information)
print(now - timedelta(hours = +9)) # =>Time minus 9 hours(No time zone information)

now = datetime.utcnow() # Naive
print(now) # =>I've pulled 9 hours now(No time zone information)
print(now + timedelta(hours = +9)) # =>Japan time plus 9 hours(No time zone information)

Class representing the time zone

tzinfo class

tzinfo is an abstract class with the following information.

--Time zone name --Time offset value from UTC --Time offset value from UTC during daylight saving time

tzinfo - datetime — Basic date and time types — Python 3.8.1rc1 documentation

Use timezone or pytz as the concrete class. pytz is not in the standard library and needs to be installed.

timezone class

timezone is a concrete class of tzinfo with a fixed offset value. It is fixed and can be used as a time zone such as +09: 00, but it cannot be considered that the offset value changes depending on the date and time such as daylight saving time.

pytz package

The pytz package allows you to generate a concrete class of tzinfo from a string like " Asia / Tokyo ". It can be considered that the offset value with UTC changes depending on the date and time.

An example where the offset value changes depending on the date and time

--Summer time in North America, Europe, Australia, etc. --In 1995, a part of Kiribati advanced the 24-hour clock. --Returned the clock for one hour in Russia in 2014

pytz is not a standard library and needs to be installed.

$ pip install pytz

Example

timezone class

from datetime import datetime
from datetime import timedelta
from datetime import timezone
import pytz

dt = datetime.utcfromtimestamp(1572764400)
print(dt)
# => 2019-11-03 07:00:00
#1572764400 is 16:00 on the 3rd in Japan time

# timezone.utc has an offset value of 0 and no daylight savings time
utc = timezone.utc
print(utc.utcoffset(dt))
# => 0:00:00
print(utc.dst(dt))
# => None

#Instance of timezone class
tz8 = timezone(timedelta(hours=-8)) #Timezone representing 8 hours behind UTC
print(tz8.utcoffset(dt))
# => -1 day, 16:00:00
print(tz8.dst(dt))
# => None

#Offset value is for Japan time+9 hours with no daylight savings time
tokyo = pytz.timezone('Asia/Tokyo') #Japan time
print(tokyo.utcoffset(dt))
# => 9:00:00
print(tokyo.dst(dt))
# => 0:00:00

#At 7 o'clock on November 3rd in UTC, the offset value is in US Pacific time.-8 hours is not daylight saving time
lasvegas = pytz.timezone('America/Los_Angeles') #American Pacific Time
print(lasvegas.utcoffset(dt))
# => -1 day, 16:00:00
print(lasvegas.dst(dt))
# => 0:00:00

#The day before, the offset value was in US Pacific time-7 hours is daylight saving time
print(lasvegas.utcoffset(dt - timedelta(days = 1)))
# => -1 day, 17:00:00
print(lasvegas.dst(dt - timedelta(days = 1)))
# => 1:00:00

datetime timezone conversion

If you use astimezone for a Naive datetime instance without timezone information, it will be converted from the local environment timezone to the specified timezone. After conversion, it becomes an Aware instance.

from datetime import datetime
from datetime import timedelta
from datetime import timezone
import pytz

dt = datetime.utcfromtimestamp(1572764400)
print(dt)
# => 2019-11-03 07:00:00
#1572764400 is 16:00 on the 3rd in Japan time

#dt is an instance created in UTC at 7 o'clock on the 3rd,
#Because it is a Naive instance with no timezone information
#It will be converted to the specified time zone as 7 o'clock on the 3rd of Japan time.

tokyo = pytz.timezone('Asia/Tokyo') #Japan time
print(dt.astimezone(tokyo))
# => 2019-11-03 07:00:00+09:00
#Since the local PC environment is Japan time, the time does not change

lasvegas = pytz.timezone('America/Los_Angeles') #American Pacific Time
print(dt.astimezone(lasvegas))
# => 2019-11-02 15:00:00-07:00
#7 o'clock on November 3rd, Japan time is 16 hours behind Japan in daylight saving time in Pacific time.

tz8 = timezone(timedelta(hours=-8)) #Timezone representing 8 hours behind UTC
print(dt.astimezone(tz8))
# => 2019-11-02 14:00:00-08:00

If you use astimezone for an Aware datetime instance with timezone information, the original timezone will be converted to the specified timezone. It will continue to be an Aware instance after conversion.

# dt.replace(tzinfo=utc)Only the time zone information is added without changing the values of year, month, day, hour, minute, and second.

print(dt.replace(tzinfo=utc).astimezone(tokyo))
# => 2019-11-03 16:00:00+09:00
print(dt.replace(tzinfo=utc).astimezone(lasvegas))
# => 2019-11-03 00:00:00-07:00
print(dt.replace(tzinfo=utc).astimezone(tz8))
# => 2019-11-02 23:00:00-08:00

Let's take a look at the conversion from UTC to Pacific Time at the end of daylight saving time.

from datetime import datetime
import pytz

lasvegas = pytz.timezone('America/Los_Angeles') #American Pacific Time

for i in range(7):
    dt = datetime.utcfromtimestamp(1572764400 + i * 1800)
    #1572764400 is UTC at 7:00 on the 3rd
    print(dt.replace(tzinfo=utc).astimezone(lasvegas))
# =>
# 2019-11-03 00:00:00-07:00
# 2019-11-03 00:30:00-07:00
# 2019-11-03 01:00:00-07:00
# 2019-11-03 01:30:00-07:00
# 2019-11-03 01:00:00-08:00 <-Time returns at the end of daylight saving time
# 2019-11-03 01:30:00-08:00
# 2019-11-03 02:00:00-08:00

19 minutes off problem

If you use dt.replace (tzinfo = tokyo) or datetime (2019, 11, 3, 1, 0, 0, tzinfo = tokyo) in the timezone object generated from pytz, 19 There is a problem that can be understood. It is 19 minutes off in Japan time, but 7 minutes off in US Pacific time.

from datetime import datetime
from datetime import timedelta
from datetime import timezone
import pytz

dt = datetime.utcfromtimestamp(1572742800)
print(dt)
# => 2019-11-03 01:00:00
#1572764400 is 1:00 on the 3rd in Japan time

utc = timezone.utc
print(dt.replace(tzinfo=utc))
# => 2019-11-03 01:00:00+00:00

If you set replace (tzinfo = utc) to an instance of Naive datetime, it will change to an Aware instance with the information of +00: 00. If you specify Japan time instead of ʻutc`,

tokyo = pytz.timezone('Asia/Tokyo') #Japan time
print(dt.replace(tzinfo=tokyo))
# => 2019-11-03 01:00:00+09:19

For some reason, the time difference is off by 19 minutes.

There is no problem if you use the method localize. I'm not sure what's different.

print(tokyo.localize(dt))
# => 2019-11-03 01:00:00+09:00

Even if I try it in US Pacific time, the deviation width is different, but it is still the same.

lasvegas = pytz.timezone('America/Los_Angeles') #American Pacific Time

print(dt.replace(tzinfo=lasvegas))
# => 2019-11-03 01:00:00-07:53

print(lasvegas.localize(dt))
# => 2019-11-03 01:00:00-08:00

Behavior at the end of daylight saving time

The 3rd day of US Pacific time is the day when daylight saving time ends, and as shown in the example above, when the time is listed every 30 minutes, the time flows as follows.

2019-11-03 00:00:00-07:00 2019-11-03 00:30:00-07:00 2019-11-03 01:00:00-07:00 2019-11-03 01:30:00-07:00 2019-11-03 01: 00: 00-08: 00 <-Time returns at the end of daylight saving time 2019-11-03 01:30:00-08:00 2019-11-03 02:00:00-08:00

It goes around twice from 1:00 to 1:59. In other words, there is ambiguity that it is not possible to tell whether it is the first time or the second time from the information of 1 o'clock.

With this fact in mind, try localize.

from datetime import datetime
from datetime import timedelta
from datetime import timezone
import pytz

dt = datetime.utcfromtimestamp(1572742800)
print(dt)
# => 2019-11-03 01:00:00
#dt is a Naive instance at 1 o'clock on the 3rd

lasvegas = pytz.timezone('America/Los_Angeles') #American Pacific Time

print(lasvegas.localize(dt))
# => 2019-11-03 01:00:00-08:00
#The second 1 o'clock was returned

By the way, if you calculate 1 hour before 1 o'clock for the second time, it will be 0 o'clock. It should be summer time at midnight, but it remains winter time.

print(lasvegas.localize(dt) - timedelta(hours=1))
# => 2019-11-03 00:00:00-08:00

If you calculate 1 hour ago for a Naive instance before localize and then localize, it will be midnight daylight saving time. This is 2 hours before the second 1 o'clock.

print(lasvegas.localize(dt - timedelta(hours=1)))
# => 2019-11-03 00:00:00-07:00

that's all.

Recommended Posts

Handling timezones in Python (datetime, pytz)
Handling json in python
Hexadecimal handling in Python 3
Relative url handling in python
Handling of JSON files in Python
Conversion of string <-> date (date, datetime) in Python
Sample for handling eml files in Python
Module import and exception handling in python
Quadtree in Python --2
CURL in python
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Unittest in python
Discord in Python
DCI in Python
quicksort in python
nCr in python
Python Error Handling
N-Gram in Python
Programming in python
Python exception handling
Plink in Python
Constant in python
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
StepAIC in Python
Python timezone handling
N-gram in python
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python
Constant in python
nCr in Python.
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Quad-tree in Python
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
LiNGAM in Python
Python exception handling
Flatten in python
flatten in python
Create a datetime object from a string in Python (Python 3.3)
Behavior when saving python datetime object in MongoDB
How to handle datetime type in python sqlite3
Sorted list in Python
Daily AtCoder # 36 in Python
Clustering text in Python
Daily AtCoder # 2 in Python
Implement Enigma in python
Daily AtCoder # 32 in Python