日付 時刻

【Python】日付、時刻を扱う基本 ~datetime~

【Python】日付、時刻を扱う基本 _datetime_

Pythonで日付を操作するためのdatetimeモジュールの使い方の基本について解説します。datetimeモジュールで日付、時刻を取得・生成する方法を中心に説明します。

日付や時刻を扱うためのdatetimeモジュール

プログラミングでは、データベースのレコードを操作する際やログ出力時など様々なケースで日付や時刻を扱う機会があります。Pythonで日付や時刻を扱う際には、datetimeモジュールをよく使用します。

datetimeモジュールの基本的な使い方について紹介していこうと思います。

Note

datetimeモジュールの公式ドキュメントの記載はこちらを参照してください。

datetimeモジュールに含まれているクラス

datetimeモジュールには以下のクラスが含まれています。必要に応じて必要なクラスを用いてプログラミングを行います。

クラス概要説明
datetime日付、時刻を扱うためのクラス
date日付を扱うためのクラス
time時刻を扱うためのクラス
timezoneタイムゾーン情報を扱うためのクラス
timedelta時間間隔を扱うためのクラス

以降では、各クラスの基本的な使い方について例を用いながら紹介していきます。

datetimeモジュールの基本的な使い方
~日付、時刻の取得・生成~

datetimeモジュールの日付や時刻は、naive型とaware型というものに分類できます。naive型はタイムゾーン情報を持たないもので、aware型はタイムゾーン情報を持っているものです。

dateクラスのオブジェクトはタイムゾーンを持ちませんのでnaive型です。datetimeクラスやtimeクラスのオブジェクトはタイムゾーンを設定するかどうかによってnaive型かaware型かが決まります。

日時を取得する方法

datetimeモジュールを使用する場合には、datetimeモジュールをインポートします。

その後、以下のようにtodayメソッド、nowメソッド、utcnowメソッドといった各種メソッドを用いて日時を取得することができます。

import datetime

# 今日の日時を表示する
print(datetime.datetime.today())

# 今日の日付を表示する
print(datetime.date.today())

# 現在の日時を表示する
print(datetime.datetime.now())

# timezoneを指定する(日本標準時)
print(datetime.datetime.now(
    datetime.timezone(datetime.timedelta(hours=9))))

# 標準時を表示する
print(datetime.datetime.utcnow())

# 標準時でtimezoneで指定する
print(datetime.datetime.now(datetime.timezone.utc))
【実行結果】
2022-03-28 06:09:47.369750
2022-03-28
2022-03-28 06:09:47.369749
2022-03-28 06:09:47.369749+09:00
2022-03-27 21:09:47.369749
2022-03-27 21:09:47.369749+00:00

上記のようにdatetimeクラスを用いると日時をまとめて取得できます。dateクラスを用いると日付の情報だけが取得されていることが分かるかと思います。

基本的に現在の時刻を取得する場合にはtodayメソッドかnowメソッドを使用します。

nowメソッドは、datetime.timezoneでタイムゾーンを指定することでaware型として取得できます。日本標準時は標準時のUTC時刻からの時差9時間なので、9時間を指定します。この時にはdateteime.timedeltaメソッドに時間間隔を指定してタイムゾーンを作成します。

なお、標準時のUTCを取得するには、標準時のUTCタイムゾーンをdatetime.timezone.utcで取得してnowに設定してaware型として取得するか、datetimeクラスのutcnowメソッドを用いてnaive型で取得することができます。

日付、時刻を指定してインスタンスを生成する方法

nowやtoday等を用いることで現在時刻を取得することができましたが、プログラマが指定した日付、時刻でインスタンスを生成したい場合があります。

その場合には、以下のように日付、時刻を指定してインスタンスを生成することができます。

import datetime

# === 日付、時刻を指定して生成する
print(datetime.datetime(2021, 1, 1, 0, 0, 0, 0))
# タイムゾーンを指定する
print(datetime.datetime(2021, 1, 1, 0, 0, 0, 0),
      datetime.timezone(datetime.timedelta(hours=9)))

# === 日付を指定して生成する ※dateクラスはタイムゾーンを指定できないので注意
print(datetime.date(2021, 1, 1))

# === 時刻を指定して生成する
print(datetime.time(0, 0, 0, 0))
# タイムゾーンを指定する
print(datetime.time(0, 0, 0, 0),
      datetime.timezone(datetime.timedelta(hours=9)))
【実行結果】
2021-01-01 00:00:00
2021-01-01 00:00:00 UTC+09:00
2021-01-01
00:00:00
00:00:00 UTC+09:00

ここで注意が必要なことは、dateクラスだけはタイムゾーンを持たないnaive型のみしか生成できないことです。datetimeクラス及びtimeクラスのインスタンスはタイムゾーンを指定することで、aware型を生成できます。

ISOカレンダーから生成する ~fromisocalendar (バージョン3.8で追加)~

日付を指定して生成する方法で使えるメソッドとして、fromisocalendarメソッドがあります。fromisocalendarメソッドは、バージョン3.8で追加されています。

fromisocalendarメソッドを使う場合には、以下のように使用します。

import datetime

# ISOカレンダーを使って生成する
dt = datetime.datetime.fromisocalendar(2022, 10, 1)
print(dt)
【実行結果】
2022-03-07 00:00:00

fromisocalendarメソッドでは、ISO年、ISO週番号、ISO曜日(1:月, 2:火, 3:水, 4:木, 5:金, 6:土, 7:日)を指定することでdatetimeインスタンスを生成できます。後述で出てくるisocalendarメソッドの逆のメソッドとなっています。

日付、時刻の文字列からインスタンスを生成する方法

日付や時刻を生成する場合には、文字列から生成したくなるケースがよくあります。その場合には、以下のようにstrptimeメソッドを用いて文字列を解析して、datetimeオブジェクトを生成することができます。

import datetime

# 日付フォーマットを指定して文字列から生成する
dt = datetime.datetime.strptime('2022/1/1 01:23:45', '%Y/%m/%d %H:%M:%S')
print(dt)
【実行結果】
2022-01-01 01:23:45

strptimeメソッドは、フォーマットを指定して、その中に含まれる年、月、日などの情報を取得した上で、datetimeクラスのインスタンスを生成する方法です。任意の文字列フォーマットでも値の取得位置を指定して取得できる点で便利です。

ISOフォーマットから生成する ~fromisoformat (バージョン3.7で追加)~

文字列から生成する方法で使えるメソッドとして、fromisoformatメソッドがあります。fromisoformatメソッドはバージョン3.7で追加されています。

fromisoformatメソッドを使う場合には、以下のように使用します。

import datetime

# ISOフォーマットの文字列から生成する
dt = datetime.datetime.fromisoformat('2022-01-01 01:23:45+09:00')
print(dt)
【実行結果】
2022-01-01 01:23:45+09:00

fromisoformatメソッドでは、決まった形の文字列からdatetimeクラスのインスタンスを生成できますが、桁数は0埋めするなどしてそろえる必要があります。例えば、2021-1-1のような表現では生成できませんので注意してください。

タイムスタンプ値からインスタンスを生成する方法

タイムスタンプ値から日付、時刻のインスタンスを生成するには、fromtimestampメソッドを使用します。タイムスタンプは、1970/01/01 00:00:00からの経過秒数のことです。

import datetime

dt = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9)))
# タイムスタンプを取得する
ts = dt.timestamp()
print(dt)
print(ts)

# タイムスタンプから日付、時刻を取得する
print(datetime.datetime.fromtimestamp(ts))
# タイムゾーンを指定する場合
print(datetime.datetime.fromtimestamp(
    ts, datetime.timezone(datetime.timedelta(hours=9))))
# UTCを指定する場合
print(datetime.datetime.fromtimestamp(
    ts, datetime.timezone.utc))
【実行結果】
2022-03-28 06:26:11.944544+09:00
1648416371.944544
2022-03-28 06:26:11.944544
2022-03-28 06:26:11.944544+09:00
2022-03-27 21:26:11.944544+00:00

タイムスタンプの値からfromtimestampメソッドを使うことで、datetimeクラスのインスタンスが生成できていることが分かります。タイムゾーンを指定しない場合は、timestampの値はnaiveとして扱われるため、naive型として値が返却されます。

aware型としたい場合には、タイムゾーンを指定します。UTCを指定した場合は、現在のタイムゾーンから時差を差し引いた値が生成されます。

日付、時刻の一部を置き換える方法

日付、時刻の一部を置き換えたい場合には、replaceメソッドを使用します。

import datetime

dt = datetime.datetime.now()
print(dt)

print('===')
# 年を変更する
print(dt.replace(year=2020))
# 月を変更する
print(dt.replace(month=1))
# 日を変更する
print(dt.replace(day=1))
# 時を変更する
print(dt.replace(hour=1))
# 分を変更する
print(dt.replace(minute=1))
# 秒を変更する
print(dt.replace(second=1))
# マイクロ秒を変更する
print(dt.replace(microsecond=123))
# タイムゾーンを変更する
print(dt.replace(tzinfo=datetime.timezone.utc))
【実行結果】
2022-03-28 06:27:53.134171
===
2020-03-28 06:27:53.134171
2022-01-28 06:27:53.134171
2022-03-01 06:27:53.134171
2022-03-28 01:27:53.134171
2022-03-28 06:01:53.134171
2022-03-28 06:27:01.134171
2022-03-28 06:27:53.000123
2022-03-28 06:27:53.134171+00:00

上記の例はdatetimeクラスでの例ですが、dateクラス、timeクラスでも同様に使用できます。

日付・時刻の要素を抽出する方法

様々な日付、時刻の取得、生成方法を見てきました。生成した日付、時刻を利用する際には、生成したインスタンスから必要な日付や時間の要素を取得する必要があります。

プロパティを使って日付・時刻の要素を抽出する

生成したインスタンスから日付・要素を抽出する場合には、以下のようにプロパティを使って簡単に取得することができます。

import datetime

# dt = datetime.datetime.now()
dt = datetime.datetime.now(
    datetime.timezone(datetime.timedelta(hours=9)))
print(dt)

print('===')
# 年を取得する
print(dt.year)
# 月を取得する
print(dt.month)
# 日を取得する
print(dt.day)
# 時を取得する
print(dt.hour)
# 分を取得する
print(dt.minute)
# 秒を取得する
print(dt.second)
# マイクロ秒を取得する
print(dt.microsecond)
# タイムゾーンを取得する
print(dt.tzinfo)
【実行結果】
2022-03-28 06:30:53.920390+09:00
===
2022
3
28
6
30
53
920390
UTC+09:00

tzinfoについては、タイムゾーンが設定されていないnaive型の場合には「None」となります。

メソッドを使って日付・時刻の要素を抽出する

生成したインスタンスから日付・要素を抽出する場合には、以下のようなメソッドがいくつか用意されています。

メソッド名処理概要
date()日付部分を取得する
time()時刻部分を取得する(naive型:タイムゾーンを含まない)
timetz()時刻部分を取得する(aware型:タイムゾーンを含む)
timestamp()タイムスタンプ値(1970/01/01 00:00:00からの経過秒数)を取得する
weekday()曜日を取得する(0:月, 1:火, 2:水, 3:木, 4:金, 5:土, 6:日)
isoweekday()曜日を取得する(1:月, 2:火, 3:水, 4:木, 5:金, 6:土, 7:日)
isocalendar()(ISO年, ISO週番号, ISO曜日)のIsoCallendarDate型を返却する
(バージョン 3.9 で変更: 結果がタプルからnamed tupleへ変更された)

各種メソッドは以下のように使用することができます。

import datetime

# dt = datetime.datetime.now()
dt = datetime.datetime.now(
    datetime.timezone(datetime.timedelta(hours=9)))
print(dt)

print('===')
# dateメソッド
print(dt.date())
# timeメソッド
print(dt.time())
# timetzメソッド
print(dt.timetz())
# timestampメソッド
print(dt.timestamp())
# weekdayメソッド
print(dt.weekday())
# isoweekdayメソッド
print(dt.isoweekday())
# isocalendarメソッド
print(dt.isocalendar())
【実行結果】
2022-03-28 06:31:14.177882+09:00
===
2022-03-28
06:31:14.177882
06:31:14.177882+09:00
1648416674.177882
0
1
datetime.IsoCalendarDate(year=2022, week=13, weekday=1)

isocalendarメソッドは、上記で出てきたfromisocalendarメソッドの逆のメソッドとなっています。もともとは、タプルが返却されるメソッドでしたが、バージョン3.9でnamed tupleに変更されています。