Pythonでdatetimeを扱うのも例外ではなく、datetimeを扱うのは少し大変で挑戦的なことです。
Pythonの組み込みモジュールである datetime
は、 date
, datetime
, time
, timezone
, timedelta
といったいくつかのクラスを導入し、Arrowなどの外部ライブラリは公式モジュールの問題点を解決するために生み出されました。
このガイドでは、Deloreanでdatetimeオブジェクトを作成し、解析する方法を見ていきます。
このライブラリは、タイムゾーンに関する問題を解決するための標準ライブラリであるpytzと、任意の2つのdatetimeオブジェクト間の差分を計算するためのdateutilをベースに構築されたライブラリです。
Deloreanのインストール 仮想環境の構築
Deloreanは、pip
経由でインストールすることができます。
一般に、仮想環境で作業することが推奨されます。
なぜなら、異なるプロジェクトで必要とされる依存関係を分離して整理することができるからです。
LinuxやMacOSで仮想環境を構築するには、以下のようにします。
$ python3 -m venv env
$ source env/bin/activate
$ python3 -m pip install delorean
または、Windowsでは、次のように実行します。
$ virtualenv env
$ .envScriptsctivate
$ python3 -m pip install delorean
デロリアン・データタイム・オブジェクトの作成
これから扱うメインのクラスは Delorean()
クラスで、これはすべての datetime オブジェクトを表します。
これを delorean
モジュールからインポートして、datetime オブジェクトのインスタンスを作成してみましょう。
from delorean import Delorean
dt_tm = Delorean()
print("Datetime: ", dt_tm)
このコードを実行すると、ターミナルやコマンドラインには次のように表示されるはずです。
Datetime: Delorean(datetime=datetime.datetime(2021, 7, 11, 18, 40, 43, 760187), timezone='UTC')
いつものように、これは標準的な datetime
オブジェクトのラッパーで、割り当てられた Delorean
オブジェクトの中に位置しています。
デフォルトのタイムゾーンは 'UTC'
ですが、オブジェクトをインスタンス化する際にタイムゾーンを定義するか、別のタイムゾーンに時間をシフトすることで簡単に切り替えることができます。
この出力は人間が解析するのは少し難しいので – 解釈しやすくするために、ラッパーからいくつかのデータを抽出することは理にかなっています。
時刻の降順の階層は明確ですが、それを目で見て解析するには時間がかかり過ぎます。
このオブジェクトの date
を取得し、それだけを表示してみましょう。
from delorean import Delorean
dt_tm = Delorean()
dt = Delorean().date
print("Date: ", dt)
この結果は
Date: 2021-07-11
もしあなたが日付に関係なく時間だけに興味があるなら、タイムゾーンを考慮した時間とタイムゾーンを考慮しない時間の両方をかなり簡単に取得できます。
from delorean import Delorean
dt_tm = Delorean()
tm = dt_tm.datetime.time()
print("Timezone-aware time: ", tm)
naive_dt_tm = dt_tm.naive
print("Timezone-naive datetime: ", naive_dt_tm)
この結果
Timezone-aware time: 18:40:21.235708
Timezone-naive datetime: 2021-07-11 18:40:21.235708
タイムゾーンを変更するには、コンストラクタの呼び出しにタイムゾーンを指定するか、時間をずらすかのどちらかです。
from delorean import Delorean
dt_tm = Delorean(timezone='Europe/Paris')
print("Datetime Object: ", dt_tm)
print("Time: ", dt_tm.datetime.time())
dt_tm.shift('US/Pacific')
print("Shifted time: ", dt_tm.datetime.time())
Datetime Object: Delorean(datetime=datetime.datetime(2021, 7, 11, 20, 43, 26, 990117), timezone='Europe/Paris')
Time: 20:43:26.990117
Shifted time: 11:43:26.990117
Deloreanはボンネットの中で pytz
を使っているので、利用可能なすべてのタイムゾーンを見るには、単純にそれらをプリントアウトすればよいのです。
import pytz
timezones = pytz.all_timezones
num = len(timezones)
print(f"There are {num} timezones:
")
for tz in pytz.all_timezones:
print(tz)
その結果
There are 593 timezones:
Africa/Abidjan
Africa/Accra
...
US/Michigan
US/Mountain
UTC
Universal
W-SU
WET
Zulu
文字列をDelorean Datetimeオブジェクトに変換する
文字列をパースしてDatetimeオブジェクトに変換する機能なしには、ライブラリは完成し ないでしょう。
Deloreanは文字列のフォーマットに対して多才で、パースされた文字列に曖昧さがある場合、 日が最初に来ると仮定します。
文字列のパースには parse()
メソッドを使用し、オプションでタイムゾーンの情報を受け付けます – そうでない場合は 'UTC'
と見なされます。
import delorean
# Datetime strings of differing formats
datetime_strings = ["Mon May 12 2021 00:01:02",
"25-12-2021", "8/6/2019",
"15-12-1987 7:00:32",
"June 5th, 2021",
"5th of April, 2012",
"Thu 13 of July"]
for date in datetime_strings:
delorean_object = delorean.parse(date)
print(delorean_object)
このコードを実行すると、次のようになります。
Delorean(datetime=datetime.datetime(2021, 5, 12, 0, 1, 2), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 12, 25, 0, 0), timezone='UTC')
Delorean(datetime=datetime.datetime(2019, 6, 8, 0, 0), timezone='UTC')
Delorean(datetime=datetime.datetime(1987, 12, 15, 7, 0, 32), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 6, 5, 0, 0), timezone='UTC')
Delorean(datetime=datetime.datetime(2012, 4, 5, 0, 0), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 7, 13, 0, 0), timezone='UTC')
8/6/2019`のあいまいなケースでは、日が最初に来ると仮定され、8月6日ではなく6月8日とパースされたことに気づきます。
また、最終的な日付の年を指定しなかったので、自動的に現在の年が割り当てられています。
もし、この挙動を変えたい場合は、 dayfirst
引数を False
に設定します。
さらに、 yearfirst
引数を True
に設定することもできる。
デフォルトでは False
で、この場合、最初に期待される値は年になる。
delorean_object = delorean.parse("8/6/2019", dayfirst=False)
print(delorean_object)
この結果は
Delorean(datetime=datetime.datetime(2019, 8, 6, 0, 0), timezone='UTC')
エポックタイムスタンプからデロリアンオブジェクトまで
現代のすべてのコンピュータは、エポック時間として知られるUNIX時間の使用を採用しているので、UNIX/エポックタイム・スタンプをデロリアン・オブジェクトに変換できるのは言うまでもありません。
これは、とにかく時間を操作するための基本的なメカニズムです。
Unix タイムスタンプを Delorean 日付時刻オブジェクトに変換するために、 delorean
モジュールの epoch()
メソッドを使用します。
import delorean
timestamp = 3141592653
delorean_object = delorean.epoch(timestamp)
print(delorean_object)
私たちは、円周率の最初の10桁を目立たないように使って、未来へのタイムスタンプを作り、このガイドの時間をはるかに超えた時間を作り出しました。
Delorean(datetime=datetime.datetime(2069, 7, 21, 0, 37, 33), timezone='UTC')
日付の羅列を生成する
Deloreanオブジェクトのシーケンスを生成する素晴らしい方法は、 stops()
ジェネレータを使用することです。
毎週火曜日、毎時間、10週間ごとなど、あるパターンに従ってN個の日付を生成することができます。
これは、例えば、毎月の支払い計画を作成したり、ROI計画を計算したりするのに便利です。
また、毎週同じ時間にスクリプトを実行して、アプリケーションからデータを収集し、集計するような、何かが発生する一連の日付を生成することができます。
しかし、そのためにはpython-crontabライブラリや、代わりにunderylingのcrontabユーティリティツールを使うことができます。
stops()ジェネレータは、頻度を表す
freq、生成する日付の数を表す
timezoneと
countを引数にとります。
周波数には、SECONDLY、
MINUTELY、
HOURLY、
DAILY、
WEEKLY、
MONTHLYまたは
YEARLY` など、有効なデロリアン定数を設定することができる。
import delorean
for stop in delorean.stops(freq=delorean.HOURLY, timezone='UTC', count=10):
print(stop)
これは、このパターンに従った一連の datetime オブジェクトを生成します。
Delorean(datetime=datetime.datetime(2021, 7, 12, 13, 35, 12), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 7, 12, 14, 35, 12), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 7, 12, 15, 35, 12), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 7, 12, 16, 35, 12), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 7, 12, 17, 35, 12), timezone='UTC')
正確に何個の datetime オブジェクトが欲しいのかわからないが、目標とする日付が決まっている場合は、指定した日付が来るまでループするように設定することもできます。
import delorean
dt1 = delorean.Delorean().naive
dt2 = delorean.Delorean(datetime=datetime.datetime(2022, 1, 1), timezone='UTC').naive
for stop in delorean.stops(freq=delorean.MONTHLY, start=dt1, stop=dt2):
print(stop)
注意: stops()
メソッドは、 start
と stop
引数にタイムゾーンを意識しない datetime インスタンスのみを受け付け、タイムゾーンを意識した日付を返します。
しかし、コンストラクタで Delorean
インスタンスを生成する際には、 timezone
を指定する必要があります。
つまり、インスタンスに timezone
を定義して、その代わりに naive
の日時を使用することになります。
このコードを実行すると、2022年の1月1日になるまで、各月の日付が表示されます。
Delorean(datetime=datetime.datetime(2021, 7, 12, 13, 46, 1), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 8, 12, 13, 46, 1), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 9, 12, 13, 46, 1), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 10, 12, 13, 46, 1), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 11, 12, 13, 46, 1), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 12, 12, 13, 46, 1), timezone='UTC')
結論
このガイドでは、PythonでDeloreanオブジェクトを作成し、パースする方法を見てきました。
文字列を様々な形式のdatetimeに変換する方法、エポックタイムスタンプをdatetimeに変換する方法、そして stops()
ジェネレータを使って一連の日付を生成する方法について見てきました。