Blow Up by Black Swan

PythonーUNIXタイムスタンプに整形する方法

[2018年11月6日一部修正: タイムゾーンの設定、datetimeオブジェクトのインポート時の記載方法]
タイムゾーン情報を持たせないとUNIXタイムスタンプ変更時にシステムのタイムゾーンの影響を受けることがわかったので、その点を修正しています。

併せて、datetimeモジュールは、同名のクラスを持ちややこしいので、そこをわかりやすくなるよう変更しました。行き詰まることが多いので、気休めに超簡単だけど、今まで知らなかったタイトルの内容についてブログを書こうと思います。やることは簡単で、文字列(str型)の時刻表記をタイムスタンプに変換するだけです。UNIXタイムスタンプとは、ある時刻を1970年1月1日からの経過秒数で表したものです。

人間の直感的には何時を表しているか全く捉えることができませんが、単なる数字列であわらされるので、コンピュータ的には扱いやすいし、保存もしやすい、一般的な時刻表記よりも保存容量が少なくて済む、などのメリットがあると思います。時刻データをデータベースなどに保存する際には、時刻をそのまま保存するよりも、UNIXタイムスタンプで保存し、出力するときに指定のタイムゾーンの時刻に変換するのが一般的らしいです。

今回の内容とフローを整理すると以下になります。

目的: DBへの保存用に時刻データをUNIXタイムスタンプに変換
内容: 文字列の時刻をUNIXタイムスタンプに変換
  変換内容: "2018-11-05T11:32:04.723"(str型) -> 1541388724.723(float型)
           ※出力時のデータ型はマイクロ秒がない時刻データでもfloat(浮動小数点)型になる
  注記: datetimeオブジェクトの関数を利用するため、時刻データをdatetime型に変換することがポイント
       解析用のフォーマットが時刻データと一致していないとエラーになる
       タイムゾーン情報を持たせないとUNIXタイムスタンプ変更時にシステムの時刻が反映されてしまう
フロー:
  1. str型の時刻を解析(str型 -> datetime型)
  2. タイムゾーン情報の付与
  3. タイムスタンプに変換(datetime型 -> float型)

具体的なコードは以下になります。

from datetime import datetime as dt

str_time = "2018-11-05T11:32:04.723"  #str型の時刻データ
dt_obj = dt.strptime(str_time, "%Y-%m-%dT%H:%M:%S.%f")  #指定したフォーマット(第2引数)で時刻データを解析し、datetime型に変換
#dt_obj -> datetime.datetime(2018, 11, 5, 11, 32, 4, 723000)

# タイムゾーンの設定 -> システム時間(私の場合はJST)に沿って変換されてしまう
tz_dt_obj = dt_obj.replace(tzinfo=datetime.timezone.utc)

timestamp = tz_dt_obj.timestamp()  #datetime型データをタイムスタンプに変換
timestamp  #float型

以上がコードです。懸念点としては、多くの時刻データを扱うときに一部の時刻データが解析用のフォーマットと一致せず、エラーが発生することかなと思います。その場合はあらかじめ、何種類かのフォーマットを用意しておく必要があるのかなと思います。

ちなみに、以前ブログ記事に書いたpandasモジュールを使えば、解析フォーマット設定せずに解析してくれますが、あまりに便利すぎる分、内部的な処理の煩雑さによるスピードや全体の処理能力の低下などの弊害などもあると思うので、時刻データのフォーマットが一定な大量のデータを扱う場合はこの方法を使用するのがベターなんじゃないかと思います。

時刻関係は個人的によく悩む議題で、過去にも拙いながら何本か記事を書いていますので、参考にして頂ければと思います。