Pythonで文字列をDatetime型に変換する方法

Pythonで文字列を時刻に変換する方法です

時刻を表す文字列

時刻を表す文字列にはいくつかのフォーマット(書式)があります

ISO8601の例

  • 2020-06-14T13:04:46+09:00

RFC 3339の例

  • 2020-06-14T04:04:46.000Z
  • 2020-06-14T04:04:46.000000Z

これらは全部同じ時刻を表しています.

末尾の"Z"や"+09:00"はタイムゾーンを表しています.
Zは“Zulu time”で +00:00,UTCと同じ意味です.+09:00は日本のタイムゾーン(JST)です.

文字列からDatetimeへの変換

ISO8601とRFC3339の書式は似ているようで,微妙に違いがあります.
両者を混在させて pythonで扱う場合には注意が必要です.

ISO8601の場合

Python 3.7以降なら datetime.datetime.fromisoformat() を使うだけで変換できます

import datetime
s = "2020-06-14T13:04:46+09:00"
print ( datetime.datetime.fromisoformat(s) )
RFC3339 の場合

文字列の末尾が"Z"の場合 datetime.datetime.fromisoformat() は, ValueErrorの例外を出します.

ValueErrorの例外の例

ValueError: Invalid isoformat string: '2020-06-14T13:04:46+09:00Z'

この場合は "Z"を無視すれば Datetimeに変換できます

import datetime
s = "2020-06-14T04:04:46.000Z"
print ( datetime.datetime.fromisoformat(s[:-1]) )

重要な点が2つあります

1点目. "Z"は +00:00 なので,

  • "2020-06-14T04:04:46.000Z"
  • "2020-06-14T04:04:46.000"
  • "2020-06-14T04:04:46.000+00:00"

は全部同じ時刻になります

2点目.

  • 2020-06-14T13:04:46+09:00
  • 2020-06-14T04:04:46.000Z

は同じ時刻です

タイムゾーンを補正しようとして
"2020-06-14T04:04:46.000+00:00"に9時間を足してしまうと
"2020-06-14T13:04:46.000+00:00"になります
これはJSTでは "2020-06-14T22:04:46.000+09:00"になります.つまり間違いです.

このように間違って+09:00を加算してしまわないようにするのがポイントになります

RFC3339形式を ISO8601形式に変換する

RFC3339形式の文字列を,ISO8601形式に変換してみます

タイムゾーンJSTに変更します

import datetime
import tz

s = "2020-06-14T04:04:46.000Z"
t =  datetime.datetime.fromisoformat(s[:-1]) 

# タイムゾーン JSTの情報を取得
JST = tz.gettz('JST')

# datetimeオブジェクト t のタイムゾーンを変更
t = t.astimezone(JST)

print ( t.isoformat() )

これで ISO8601形式で '2020-06-14T13:04:46+09:00' が表示されます