ログや時系列情報を含むデータを読み込んで、日付やタイムスタンプの文字列を変換してdatetimeオブジェクトとして扱いたいというケースがよくあります。
タイムスタンプ情報の書式はデータにより様々なフォーマットに表現されているので、適切に変換するにはちょっとしたコツが必要です。
ただ、一度覚えてしまえば様々なシーンで活用することが出来ます。
datetime モジュールについて
Python で日付や時間情報を取り扱う際には datetime モジュールを利用するのが一般的です。
このモジュールは標準で提供されており、Python が動作する全ての環境で利用できます。
datetime モジュールには、日付に関するクラスとして date クラスと datetime クラスなどが提供されており、Python で日付を扱うには、このふたつを抑えておく必要があります。
date クラス
datetime モジュールで実装されている date クラスは日付に関する情報を扱うことが可能で以下の属性を持ちます。
属性 | 内容 |
---|---|
year | 年を表す datetime.MINYEAR から datetime.MAXYEAR までの数値 |
month | 月を表す 1 から 12 までの数値 |
day | 月中の日にちを表す 1 から year month が表す年月の月末日までの数値 |
サンプルコード
from datetime import date # 今日の日付を taday メソッドで取得して出力 print(date.today())
出力結果
2018-07-29
実行時の日付が date オブジェクトとして返されています。
(サンプルの実行結果では 2018年7月29日 となっています。)
datetime クラス
datetime モジュールで実装されている datetime クラスは日付と時間を組み合わせたデータ型でdateクラスの属性に加えてさらに以下の属性を持ちます。
属性 | 内容 |
---|---|
hour | 時間を表す 0 から 23 までの数値 |
minute | 分を表す 0 から 59 までの数値 |
second | 秒を表す 0 から 59 までの数値 |
サンプルコード
from datetime import datetime # 現在のタイムスタンプを now メソッドで取得して出力 print(datetime.now())
出力結果
2018-07-29 18:30:27.120792
実行時のタイムスタンプが datetime オブジェクトとして返されています。
(サンプルの実行結果では、 2018年7月29日 18時30分27.120792秒 となっています。)
datetime クラスの strptime メソッドを使う
日時を表す文字列を datetime オブジェクトに変換する方法としては
これが最もオーソドックスで汎用性の高い方法です。
さっそく変換してみましょう。
シンプルなタイムスタンプ文字列の変換
まずは、最もオーソドックスな「YYYYMMDD」形式の文字列を変換してみます。
サンプルコード
from datetime import datetime # 変換対象の日付文字列 ts = '2018/07/29 13:50:29' # 文字列から datetime オブジェクトを生成 dt = datetime.strptime(ts,'%Y/%m/%d %H:%M:%S') # 変換結果を確認するため出力 2018-07-29 13:50:29 print(dt)
出力結果
2018-07-29 13:50:29
サンプルの実行結果では、2018年7月29日 13時50分29秒 となっています。
但し、この方法で生成されたdatetime オブジェクトはタイムゾーンの情報が含まれていません。
解説
サンプルコードを見ていただくと、strptime メソッドに2つの引数を渡しています。
- 第1引数 変換対象の文字列
- 第2引数 文字列の書式
第2引数の ‘%Y/%m/%d %H:%M:%S’ についてもう少し詳しく見て見ましょう。
書式として指定されている記号については、それぞれ以下のような意味合いがあります。
スラッシュとセミコロン、スペース文字については区切り文字として解釈されています。
表記 | 内容 |
---|---|
%Y | 西暦(4桁)の10進数表記を表します。 |
%m | 0埋めした10進数で表記した月。 |
%d | 0埋めした10進数で表記した月中の日にち。 |
%H | 0埋めした10進数で表記した時(24時間表記) |
%M | 0埋めした10進数で表記した分。 |
%S | 0埋めした10進数で表記した秒。 |
米国表記の日付文字列を変換してみよう
米国では、「月日年 時分秒」で日付を表現するケースが多いです。
例えば、「Jul 31 2018 1:45PM」は 「2018年7月31日 13時45分」となります。
これを Pythonで実現すると以下のようなコードになります。
サンプルコード
from datetime import datetime # 変換対象のタイムスタンプ文字列 timestamp_str1 = 'Jul 31 2018 1:45PM' # 文字列から datetime オブジェクトを生成 dt = datetime.strptime(timestamp_str1,'%b %d %Y %I:%M%p') # 変換結果を確認するため出力 2018-07-31 13:45:00 print(dt)
出力結果
解説
第2引数の ”%b %d %Y %I:%M%p” についてもう少し詳しく見て見ましょう。
書式として指定されている記号については、それぞれ以下のような意味合いがあります。
表記 | 内容 |
---|---|
%b | ロケールの月名を表示します。 |
%d | 0埋めした10進数で表記した月中の日にち。 |
%Y | 西暦(4桁)の10進数表記を表します。 |
%I | 0埋めした10進数で表記した時(12時間表記) |
%M | 0埋めした10進数で表記した分。 |
%p | ロケールのAMもしくはPMと等価な文字列になります。 |
フォーマット文字列一覧
フォーマットの文字列一覧は、以下となります。
ディレクティブ | 意味 | |
---|---|---|
%a |
ロケールの短縮された曜日名になります。 | |
%A |
ロケールの曜日名になります。 | |
%b |
ロケールの短縮された月名になります。 | |
%B |
ロケールの月名になります。 | |
%c |
ロケールの日時を適切な形式で表します。 | |
%d |
月中の日にちの 10 進表記になります [01,31]。 | |
%H |
時 (24 時間表記) の 10 進表記になります [00,23]。 | |
%I |
時 (12 時間表記) の 10 進表記になります [01,12]。 | |
%j |
年中の日にちの 10 進表記になります [001,366]。 | |
%m |
月の 10 進表記になります [01,12]。 | |
%M |
分の 10 進表記になります [00,59]。 | |
%p |
ロケールの AM もしくは PM と等価な文字列になります。 | |
%S |
秒の 10 進表記になります [00,61]。 | |
%U |
年の初めから何週目か (日曜を週の始まりとします) を表す 10 進数になります [00,53]。年が明けてから最初の日曜日までのすべての曜日は 0 週目に属すると見なされます。 | |
%w |
曜日の 10 進表記になります [0 (日曜日),6]。 | |
%W |
年の初めから何週目か (月曜を週の始まりとします) を表す 10 進数になります [00,53]。年が明けてから最初の月曜日までの全ての曜日は 0 週目に属すると見なされます。 | |
%x |
ロケールの日付を適切な形式で表します。 | |
%X |
ロケールの時間を適切な形式で表します。 | |
%y |
西暦の下 2 桁の 10 進表記になります [00,99]。 | |
%Y |
西暦 ( 4桁) の 10 進表記を表します。 | |
%z |
タイムゾーンと UTC/GMT との時差を表す正または負の時間を +HHMM、-HHMM で表します。H は時間の、M は分の 10 進表記になります [-23:59, +23:59]。 | |
%Z |
タイムゾーンの名前を表します (タイムゾーンがない場合には空文字列)。 | |
%% |
文字 '%' を表します。 |
電子メール形式の日付文字列を変換
電子メールやHTTPヘッダーでは、日付をRFC2822のフォーマット形式で表現されています。
例えば、’Sun, 29 Jul 2018 15:45:23 +0900′ といった文字列を解釈して datetime へ変換してみましょう。
これを Python で変換するには以下のようなコードになります。
サンプルコード
from datetime import datetime,timezone,timedelta # 変換対象の日付文字列 date_str1= 'Sun, 29 Jul 2018 15:45:23 +0900' # 日時情報を生成(タイムゾーン情報なし) ts = '' for s in date_str1.split()[1:5]: ts += s # 取得した日付情報から naive な datetime オブジェクトを生成 d = datetime.strptime(ts, '%d%b%Y%H:%M:%S') # タイムゾーン情報を文字列から取得 tzs = date_str1.split()[5] if tzs[0] == '+': sign = 1 else: sign = -1 h = int(tzs[1:3]) m = int(tzs[3:]) # タイムゾーン情報を生成 TZ = timezone(timedelta(hours=(sign * h),minutes=(sign * m))) # 生成済みの naive な datetime とタイムゾーン情報から aware な datetime オブジェクトを生成 dt = datetime(d.year,d.month,d.day,d.hour,d.minute,d.second,0,tzinfo=TZ) # 変換結果を確認するため出力 2018-07-29 15:45:23+09:00 print(dt)
出力結果
2018-07-29 15:45:23+09:00
期待どおり、2018年7月29日 の15時45分23秒 となっていますね。
タイムゾーン情報も設定されていることがわかります。
解説
1行目から11行目では、これまでと同様に日付文字列から strptimr メソッドで datetime オブジェクトを生成しています。
ただしこの方法では、タイムゾーン情報を持たない naive なdatetime オブジェクトを生成することしかできません。
タイムゾーン情報を持たせるには、aware な datetime オブジェクトを生成する必要があります。
そこで13行目から20行目で、文字列からタイムゾーン情報を取得します。
23行目でタイムゾーン情報を生成し、最後に25行目でタイムゾーン情報を付与した datetime オブジェクトを生成して終わりです。
まとめ
日付文字列をPython の datetime オブジェクトへ変換する方法について紹介させていただきました。
以下にポイントをまとめておきます。
- Python で日時情報を扱うには datetime クラスを使う。
- 日時情報を変換するには datetime クラスの strptime メソッドを使う。
- strptime メソッドの第2引数にフォーマット文字列を指定することでさまざまな日付フォーマット形式に対応することができる。
- strptime メソッドで生成される datetime オブジェクトは naive なオブジェクトであり、タイムゾーン情報を含んでいない。
- aware な datetime を生成するにはタイムゾーン情報を渡す必要がある。
まとめ2
strptimenの変換
strptimeは「文字列」を「日付」に変換します。
たとえば 2018-08-10 という文字を 年-月-日 と解釈して変換するには、以下のように strptime を使います。
from datetime import datetime
d = datetime.strptime(“1991-11-05”, “%Y-%m-%d”)
print(d.year) # 1991という数字になります
print(d.month) # 11という数字になります
print(d.day) # 5という数字になります
詳しくは、strptime()を参照ください。
strftime
strftimeは「日付」を「文字列」に変換します。
たとえば datetime(2018, 11, 5) という日付を 年-月-日 というハイフン区切りの文字列に変換するため、以下のように strftime を使います。
d = datetime(2018, 11, 5) # 1991年11月5日の、日付を変数dに入れる
print(d.strftime(“%Y-%m-%d”)) # 年-月-日として文字列にする
strptimeだけでなく、strftimeの変換を行うことはできます。
しっかりと抑えておくと良いと思いまます。
「strftime() と strptime() の振る舞い」の違いを知りたい方は、下記を参照ください。
「strftime() と strptime() の振る舞い」
https://docs.python.jp/3/library/datetime.html#strftime-strptime-behavior