Blow Up by Black Swan

Python-時刻を解析する2つの方法

Pythonで時刻を解析する方法を2つ学んだので、今回はそれについて記事を書こうと思います。

1. 時刻解析の2つの方法とは?そのメリット・デメリット

今回学んだ2つの方法とは以下になります。

  • datetimeモジュールのstrptimeメソッドを利用する
  • dateutilモジュールのparser.parseメソッドを利用する

datetimeモジュールのメリットとしては、以下が考えられます。

  • 標準モジュールのため、新たにインストールする必要がない

デメリットとしては、以下があります。

  • 解析用の時刻に一致する時刻フォーマットを設定しなければならない
  • そのため、時刻表記が複数ある時刻データをループ解析するのには不向き

一方で、dateutilモジュールのメリット・デメリットは以下になります。

  • 時刻解析のフォーマットを指定する必要がないため、柔軟な対応が可能
  • サードパーティーモジュールのため、新たにインストールする必要がある

2. コード例

以下が実際のコード例になります。上記の説明に合わせ、datetime.strptimeメソッドから順に記載していきます。

・datetimeモジュールのstrptimeメソッド

まずは、datetimeモジュールのstrptimeメソッドです。フォーマットの厳密な指定が必要であることがわかるよう、マイクロ秒があるかないかという点での差でフォーマットの一致不一致の場合を検証しています。

#1-1.datetimeモジュール(マイクロ秒があり、フォーマットに一致する)

from datetime import datetime as dt

str_time = '2018-07-08T12:13:37.91'
parse_time = dt.strptime(str_time, '%Y-%m-%dT%H:%M:%S.%f')
print(parse_time)
parse_time

strptimeメソッドの引数は、第1引数が文字列の時刻、第2引数がその時刻を解析するためのフォーマットです。上記コードの戻り値は以下になります。文字列の時刻がdatatime型の時刻に変換され、yearやmonthなどの属性値に正しい数値が保持されています。一方で、naiveな時刻オブジェクトになります。

2018-07-08 12:13:37.910000  # <- print(parse_time)の結果
Out[12]:datetime.datetime(2018, 7, 8, 12, 13, 37, 910000)

一方で、strptimeメソッドの時刻と解析フォーマットが不一致の場合は以下になります。

#1-1.datetimeモジュール(マイクロ秒がなく、フォーマットに一致しない)

from datetime import datetime as dt

str_time = '2018-07-08T12:13:37' #マイクロ秒がない文字列時刻
parse_time = dt.strptime(str_time, '%Y-%m-%dT%H:%M:%S.%f')  #解析用フォーマットではマイクロ秒が存在する仕様になっている
print(parse_time)
parse_time

このコードを実行すると、以下のようなエラーが出ます。

---(省略)---
ValueError: time data '2018-07-08T12:13:37' does not match format '%Y-%m-%dT%H:%M:%S.%f'

この点がstrptimeメソッドの使いづらさかなと思います。

・dateutilモジュールのparser.parseメソッド

次は、dateutilモジュールのparser.parseメソッドです。上記とほぼ同じコードを使います。

#2-1.dateutilモジュール(マイクロ秒がある場合)

from dateutil.parser import parse

str_time = '2018-07-08T12:13:37.91'
parse_time = parse(str_time)
print(parse_time)
parse_time

parseメソッドの引数には、文字列の時刻情報を指定するだけで、フォーマットの指定は必要ありません。戻り値は以下のようにdatetime型になります。これもyearやmonthなどの属性に適切な数値が保持されています。ただし、こちらもnaiveな時刻オブジェクトになります。

2018-07-08 12:13:37.910000  # <- print(parse_time)
Out[14]:datetime.datetime(2018, 7, 8, 12, 13, 37, 910000)

次は、datetimeモジュールの時の検証と同じように、マイクロ秒がない文字列時刻を解析する場合です。

#2-1.dateutilモジュール(マイクロ秒が無い時刻の場合)

from dateutil.parser import parse

str_time = '2018-07-08T12:13:37'  #マイクロ秒がない
parse_time =parse(str_time)
print(parse_time)
parse_time

しかし、datetimeモジュールと違い、エラーは起こらず、正しく解析されます。

2018-07-08 12:13:37
Out[9]:datetime.datetime(2018, 7, 8, 12, 13, 37)

3. まとめ

以上が今回学んだ時刻解析の2つの方法です。dateutilを使っておけばいいじゃんと思いそうなところではありますが、これだけ簡便に解析ができる分コード全体のスピードなどに影響を与えるんじゃないかと思います。その点は大規模システムやビッグデータ解析などの時にはっきりとあわられてくるんじゃないかと思いますが、今回は特に検証していません。機会があれば、そういった検証もしたいなと思います。

今回も誰か1人でも参考になれば幸いです。

主要参考サイトについては、少し前に学んだこともあり、どれかが判然とせず、今回は載せておりません・・・