ISO8601 フォーマットの日付を読み取る方法
この記事では、時刻を表記する際の国際標準フォーマットである ISO8601 形式を Python で扱う方法について説明します。
ISO8601 に従う時刻表記については、Python に限った話ではありません。詳しくは別の記事 「ISO 8601 の時刻表記」をみてください。
最近では、海外との商取引が増えているところも多いのではないでしょうか。
グローバルな環境で使うコンピュータシステムを構築するにあたり、気をつけるポイントはいくつかありますが、 特に気をつけないといけないもののひとつは日付や時刻です。
例えばアメリカ国内だけで考えても、いくつもタイムゾーンがあるので、「何月何日何時」というだけでは情報として足りず、 タイムゾーンも含めて表記しないとあいまいさが残ってしまいます。
そのため、日付や時刻を表すのに統一した表記が必要となるわけで、その標準としてよく使われるのが ISO8601 フォーマット です。
日本時刻の 2018年1月1日午前10時30分なら、日本のタイムゾーンは UTC+9時間ですから、2018-01-01T10:30+0900 のように書きます。
省略形などその他の書き方もあります。
ここでは ISO8601 フォーマットの時刻を扱う例を紹介します。
環境設定
まずは環境設定です。ここでは pytz パッケージと iso8601 パッケージをインストールします。
テスト用の環境として、個別に環境を作るには virtualenv を利用すると他に影響を与えないので便利です。「Virtualenv の使い方」をみてください。
タイムゾーンを扱うのに pytz パッケージを使います。pip でインストールできます。
$ pip install pytz
同様に iso8601 パッケージをインストールするには、次のコマンドでインストールできます。
$ pip install iso8601
ISO8601 フォーマットの日付・時刻を読み取る
動作例は次の通りです。次のスクリプトを timestamp1.py として保存してください。
import pytz
import iso8601
from datetime import datetime
txt = '2010-04-01T09:00:00-07:00'
print('Original Text : ' + txt)
# Parse Text
p = iso8601.parse_date(txt)
print('Parsed date : ' + str(p))
print('UTC Offset : ' + str(p.utcoffset()))
# UNIX Timestamp
ts = int(p.timestamp())
print('UNIX timestamp : ' + str(ts))
# ISO Format - UTC
utc_tz = pytz.timezone('UTC')
d = datetime.fromtimestamp(ts, utc_tz).isoformat()
print('ISO Format UTC : ' + d)
# ISO Format - LA
la_tz = pytz.timezone('America/Los_Angeles')
d = datetime.fromtimestamp(ts, la_tz).isoformat()
print('ISO Format LA : ' + d)
ここでは Python3.6 を利用しています。
このスクリプトの実行結果は次のようになります。
$ python timestamp1.py Original Text : 2010-04-01T09:00:00-07:00 Parsed date : 2010-04-01 09:00:00-07:00 UTC Offset : -1 day, 17:00:00 UNIX timestamp : 1270137600 ISO Format UTC : 2010-04-01T16:00:00+00:00 ISO Format LA : 2010-04-01T09:00:00-07:00
それぞれの出力内容について説明します。
このスクリプトでは 2010-04-01T09:00:00-07:00 という ISO8601フォーマットの文字列が渡されています。
import pytz
import iso8601
from datetime import datetime
txt = '2010-04-01T09:00:00-07:00'
print('Original Text : ' + txt)
オリジナルテキストとしてそれをそのまま表示しています。
次に iso8601 パッケージの parse_date 関数によって、文字列の内容を読み取り datetime オブジェクトにします。
# Parse Text
p = iso8601.parse_date(txt)
print('Parsed date : ' + str(p))
print('UTC Offset : ' + str(p.utcoffset()))
これらの出力は次の通りです。
Parsed date : 2010-04-01 09:00:00-07:00 UTC Offset : -1 day, 17:00:00
確かに内容が取り込まれています。UTC からのオフセットは、つまりタイムゾーンになるわけですが、これも確かに認識されていることがわかります。
ただ、「UTC からマイナス 7 時間」と言えば簡単に思えますが、出力は「1 日マイナスでプラス 17時間」という内容が書いています。24時間マイナスで、そこからプラス 17 時間ということで、 確かに差し引きマイナス 7 時間ですが、やや分かりにくいですね。
UNIX タイムスタンプも次の通りとれています。
# UNIX Timestamp
ts = int(p.timestamp())
print('UNIX timestamp : ' + str(ts))
UNIX timestamp : 1270137600
UNIX タイムスタンプは UTC 時刻の 1970 年 1 月 1 日午前 0 時 0 分 0 秒からの経過秒です。
さらに UNIX タイムスタンプから、また ISO フォーマットに戻すには次のようにします。
次の例では同じ UNIX タイムスタンプ UTC 時刻とロサンゼルス時刻を ISO フォーマットで表示しています。
# ISO Format - UTC
utc_tz = pytz.timezone('UTC')
d = datetime.fromtimestamp(ts, utc_tz).isoformat()
print('ISO Format UTC : ' + d)
# ISO Format - LA
la_tz = pytz.timezone('America/Los_Angeles')
d = datetime.fromtimestamp(ts, la_tz).isoformat()
print('ISO Format LA : ' + d)
ISO Format UTC : 2010-04-01T16:00:00+00:00 ISO Format LA : 2010-04-01T09:00:00-07:00
確かに元の文字列から UNIX タイムスタンプまで変換した後からでも、もとの表記に戻せています。
以上、ISO8601 フォーマットでの文字列の扱い方について説明しました。