detetimeモジュールは、カレンダー(グレゴリオ暦)の日付とその時刻を扱うための便利なクラスを提供しています。特定の日時から何日後や何時間後(あるいは何日前、何時間前)といった日時に対する演算のサポートや、フォーマットにしたがって文字列へ変換するなど、日時に対する便利な機能を数多く提供します。
datetimeモジュールは次のクラスを提供しています。
- dateクラス:年月日を扱う
- timeクラス:時分秒を扱う
- detetimeクラス:日付と時刻の両方を扱う
- timedeltaクラス:日付および時刻の間隔、つまり「期間」を扱う
- tzinfoクラス:タイムゾーンを扱う
これらのオブジェクトはすべてイミュータブル(変更不可能)です。
この記事では、これらのクラスについて詳しく解説します。最初にtimedeltaオブジェクトの説明から始めます。これはdateやdatetimeオブジェクトの演算でtimedeltaオブジェクトの理解が必要だからです。
ただし、tzinfoクラスについては詳しく扱いません。tzinfoクラスはタイムゾーンを扱うクラスですが、プログラムが単一の環境で動作するような場合、タイムゾーンを考慮しなくても問題になりません。タイムゾーンを正しく扱うには高度な知識と奇妙な慣習と向き合う必要があり、本稿の範疇を超えてしまいます。
最後にオブジェクトをフォーマットにしたがって文字列に変換するstrftime()と、文字列を解析してdatetimeオブジェクトを生成しるstrptime()について説明します。
詳しい説明の前に知っておくべきこと
datetimeモジュールで日時を扱うときに知っておくべき前提知識がいくつかあります。ここではそれらを簡単に説明します。
日時に関する用語
最初にこの記事を理解するために最低限必要な日時に関する一般的な用語を説明します。
- UTC(Universal time coordinated: 協定世界時)
-
UTCは世界各地の標準時の基準として用いられる時刻です。かつてはグリニッジ標準時(GMT)が世界の標準時として広く使われていたが、今では多くの分野でUTCが使われるようになりました。
世界各地の標準時はこのUTCを基準としており、日本標準時(JST)はUTCより9時間進んでいる(UTCが午前0時のとき、JSTでは午前9時)。
- UNIX時間
-
UNIX時刻、POSIXタイム、エポック秒など、さまざま名前で呼ばれることもあるが、これはUTCの1970年1月1日午前0時0分0秒からの経過秒数で時刻を表現します。起点となる1970年1月1日午前0時0分0秒のことをエポックと呼びます。
- タイムゾーン
-
タイムゾーンは「同じ標準時を使う地域の集まり」のことです。コンピュータにはタイムゾーンを設定することができ、これにより運用される時刻が決まります。タイムゾーンはUTCを基準時とし、基準時からのオフセットで表現されます。日本標準時(JST)の場合は「UTC+9」と表記されます。
nativeとawareなオブジェクト
datetimeクラスとtimeクラスのオブジェクトはタイムゾーン(tzinfoのサブクラスのインスタンス)の情報を含むことができます。タイムゾーンを含む場合はaware、含まない(Noneに設定されている)場合はnativeに分類されます(dateクラスのオブジェクトは常にnativeです)。
nativeなオブジェクトはタイムゾーンを持っていない、つまりオブジェクト自体からUTCの日時を表しているか、特定の地域のローカルな日時を表しているかがわかりません。一方、awareなオブジェクトは完全に特定の日時を表すものです。
nativeなオブジェクトとawareなオブジェクは性質の異なるものなので比較などの操作は意味がありません(間違いと言っていいでしょう)。
前述した通り、この記事ではタイムゾーンは扱いません。つまりオブジェクトがタイムゾーンの情報を持たないnativeなオブジェクトを前提として解説します。
detetimeモジュールの属性
detetimeモジュールには、このモジュールが提供するクラスが扱える最小および最大の年を属性として定義しています。最小の年はMINYEAR、最大の年はMAXYEARです。
>>> import datetime
>>> datetime.MINYEAR
1
>>> datetime.MAXYEAR
9999
関連するモジュール
関連するモジュールとしては、timeモジュールがあります。この後の解説の中で少しですがtimeモジュールのメソッドが出てきます。timeモジュールについては次の記事で詳しく解説していますので併せてご覧ください。
timedeltaオブジェクトの解説
timedeltaクラスは日時の差、つまり「期間」を表すオブジェクトです。
timedeltaオブジェクトは、日(days)、秒(seconds)、マイクロ秒(microseconds)、分(minutes)、時(hours)、週(weeks)を引数として作成できます。
全ての引数はオプションで、デフォルト値は0です。引数は整数、浮動小数点数のどちらでもよく、正でも負でも構いません。
>>> from datetime import timedelta
>>> delta = timedelta(days=1, seconds=1, microseconds=1, minutes=1, hours=1, weeks=1)
timedeltaオブジェクトは、内部的にdays、seconds、microsecondsの3つの値だけデータを管理しています。
>>> delta
datetime.timedelta(days=8, seconds=3661, microseconds=1)
そのためdays=1、weeks=1は内部的にdays=8にまとめられ、hours=1、minutes=1、seconds=1はseconds=3661にまとめられます。microseconds=1は、この場合そのままです。timedeltaオブジェクトが負の値を持つときはseconds、microsecondsの値は必ず正の値になり、daysだけが負の値になります。
内部的に保持されるdays、seconds、microsecondsは属性として参照できます。
>>> delta.days
8
>>> delta.seconds
3661
>>> delta.microseconds
1
timedelta()の引数にはtimedeltaオブジェクトが表現できる範囲内の値を指定する必要があります。timedeltaオブジェクトで表現できる最小値と最大値は、クラス属性として定義されています。timedeltaオブジェクトが表現できる範囲を超えるような引数を渡すとOverflowErrorを送出します。
>>> timedelta.min
datetime.timedelta(days=-999999999)
>>> timedelta.max
datetime.timedelta(days=999999999, seconds=86399, microseconds=999999)
インスタンスメソッド — total_seconds()
timedeltaオブジェクトの唯一のインスタンスメソッドはtotal_seconds()です。このメソッドはトータルの秒数を浮動小数点数で返します。
>>> h = timedelta(hours=100)
>>> h.total_seconds()
360000.0
total_seconds()が返す値は、丸められる可能性があることに注意してください。
>>> timedelta.max
datetime.timedelta(days=999999999, seconds=86399, microseconds=999999)
>>> timedelta.max.total_seconds()
86400000000000.0
timedeltaオブジェクトの演算
timedeltaオブジェクトはいくつかの演算をサポートしています。ここで説明する演算の他、dateおよびdatetimeオブジェクトとの加減算もサポートしています。
timedeltaオブジェクトがサポートする算術演算には次のものがあります。演算の結果、timedeltaオブジェクトの最大値または最小値を超える場合はOverflowErrorを送出します。また0による除算はZeroDivisionErrorを送出します。下記の表には演算で送出する可能性のある例外も付記します。
算術演算 | 結果 |
---|---|
td1 = td2 + td3 | timedeltaオブジェクトの加算 例外:OverflowError |
td1 = td2 – td3 | timedeltaオブジェクトの減算 例外:OverflowError |
td1 = td2 * i (または td1 = i * td2) | timedeltaオブジェクトとint型の乗算 例外:OverflowError |
td1 = td2 * f(または td1 = f * td2) | timedeltaオブジェクトとfloat型の乗算。結果は丸められる可能性がある 例外:OverflowError |
f = td2 / td3 | timedeltaオブジェクトの除算。float型を返す 例外:ZeroDivisionError |
td1 = td2 / i | timedeltaオブジェクトとint型の除算。結果は丸められる可能性がある 例外:ZeroDivisionError |
td1 = td2 / f | timedeltaオブジェクトとfloat型の除算。結果は丸められる可能性がある 例外:OverflowError、ZeroDivisionError |
i = td2 // td3 | timedeltaオブジェクトの除算(余り切り捨て)。int型を返す 例外:ZeroDivisionError |
td1 = td2 // i | timedeltaオブジェクトとint型の除算(余り切り捨て) 例外:ZeroDivisionError |
td1 = td2 % td3 | timedeltaオブジェクトの剰余 例外:ZeroDivisionError |
+td | 同じ値を持つ新しいtimedeltaオブジェクトを返す |
-td | td * -1 と同じ 例外:OverflowError |
次にtimedeltaオブジェクトの算術演算の例をいくつか示します。
>>> td1 = timedelta(days=3)
>>> td2 = timedelta(days=1, hours=12)
>>> str(td1 + td2)
'4 days, 12:00:00'
>>> str(td2 - td1)
'-2 days, 12:00:00'
>>> str(td2 * 2)
'3 days, 0:00:00'
>>> str(td1 * 1.5)
'4 days, 12:00:00'
>>> str(td1 / 2)
'1 day, 12:00:00'
timedeltaオブジェクトは比較演算もサポートしています。不等号で異なる型との比較はTypeErrorを送出します。等号では異なる型との比較でも常にbool値を返します。
比較演算 | 結果 |
---|---|
td1 == td2 | td1とtd2が等しければTrue。そうでなければFalse。 |
td1 != td2 | td1とtd2が等しくなければTrue。そうでなければFalse。 |
td1 < td2 (td2 > td1) | td1よりtd2が大きければTrue。そうでなければFalse。 例外:TypeError |
td1 <= td2 (td2 => td1) | td1とtd2が等しい、またはtd1よりtd2が大きければTrue。そうでなければFalse。 例外:TypeError |
次にtimedeltaオブジェクトの比較演算の例をいくつか示します。
>>> str(td1)
'3 days, 0:00:00'
>>> str(td2)
'1 day, 12:00:00'
# 同値性の比較
>>> td1 == td2
False
>>> td1 != td2
True
>>> td1 == td2 * 2
True
# == および != は異なる型のオブジェクトの比較でもbool値を返す
>>> td1 == 3
False
>>> td1 != 3
True
# 不等号での比較
>>> td1 < td2
False
>>> td1 > td2
True
>>> td1 <= td2 * 2
True
# 不等号で異なる型との比較はTypeErrorを送出する
>>> td1 < 100
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'datetime.timedelta' and 'int'
timedeltaオブジェクトはいくつかの組み込み関数に渡すこともできます。
組み込み関数 | 結果 |
---|---|
abs(td) | tdの絶対値を返す。td.days >= 0 のときには +td、td.days < 0 のときには -td となる。 |
tuple = divmod(td1, td2) | 商と剰余をタプルで返す。 例外:ZeroDivisionError |
dateオブジェクトの解説
dateオブジェクトはグレゴリオ暦の日付(年月日)を表します。dateオブジェクトは次のように年月日を引数として作成できます。全ての引数が必須です。
datetime.date(year, month, day)
それぞれの引数に指定できる範囲は次のとおりです。範囲を超える引数を与えるとValueErrorが送出されます。
- datetime.MINYEAR <= year <= datetime.MAXYEAR
- 1 <= month <= 12
- 1 <= day <= 指定された年の月の日数
次の例は年月日を引数としてdateオブジェクトを作成します。
>>> from datetime import date
>>> d = date(2022, 7, 4)
>>> d
datetime.date(2022, 7, 4)
年、月、日はオブジェクトの属性としてアクセスできます。
>>> d.year
2022
>>> d.month
7
>>> d.day
4
dateオブジェクトで表現できる最大値と最小値はクラス属性として定義されています。
>>> date.min
datetime.date(1, 1, 1)
>>> date.max
datetime.date(9999, 12, 31)
今日の日付のオブジェクトを取得 — today()
クラスメソッドtoday()は今日の日付のdateオブジェクトを返します。これはローカルな日付です。
>>> today = date.today()
>>> today
datetime.date(2023, 5, 25)
オブジェクトを生成するクラスメソッド — fromtimestamp()、fromisoformat()、fromisocalendar()
time.time()が返すようなUNIX時間(POSIX タイムスタンプ)からローカルな日付のdateオブジェクトへ変換することもできます。それにはクラスメソッドfromtimestamp()を使います。
>>> import time
>>> date.fromtimestamp(time.time())
datetime.date(2023, 5, 25)
有効なISO 8601形式の文字列からdateオブジェクトを生成することもできます。それにはクラスメソッドfromisoformat()を使います。
>>> date.fromisoformat('2022-07-04')
datetime.date(2022, 7, 4)
>>> date.fromisoformat('20220704')
datetime.date(2022, 7, 4)
>>> date.fromisoformat('2023W012')
datetime.date(2023, 1, 3)
>>> date.fromisoformat('2023-W01-2')
datetime.date(2023, 1, 3)
クラスメソッドfromisocalendar()は、ISO 8601暦の年、週番号、日番号からdateオブジェクトを生成します。
>>> date.fromisocalendar(2023, 1, 2)
datetime.date(2023, 1, 3)
文字列へ変換する — isoformat()、ctime()、strftime()
isoformat()メソッドは、ISO 8601のYYYY-MM-DD形式の文字列を返します。
>>> d.isoformat()
'2023-03-21'
ctime()メソッドは、日付をtime.ctime()と同じ形式の文字列で返します。
>>> d.ctime()
'Tue Mar 21 00:00:00 2023'
strftime()メソッドは書式指定文字列にしたがって文字列に変換した文字列を返します。strftime()メソッドの詳細は後述します。
>>> d.strftime('%Y/%m/%d')
'2023/03/21'
その他のインスタンスメソッド — replace()、weekday()、isoweekday()、isocalendar()
replace()メソッドは年、月、日を置換した新しいdateオブジェクトを返します。
>>> d = date(2023, 3, 21)
>>> d.replace(year=2012, month=6, day=11)
datetime.date(2012, 6, 11)
この例ではキーワード引数の名前を示すためにyear、month、dayの全てを指定しています。省略された引数の値は、元の値と同じまま変わりません。
weekday()とisoweekday()メソッドは、曜日を表す整数を返します。weekday()の場合は月曜日は0、日曜日は6です。isoweekday()の場合は月曜日が1、日曜日は7になります。
>>> d.weekday()
1
>>> d.isoweekday()
2
isocalendar()メソッドは、ISO 8601暦の名前付きタプルを返します。
>>> d.isocalendar()
datetime.IsoCalendarDate(year=2023, week=12, weekday=2)
dateオブジェクトの演算
dateオブジェクトはいくつかの算術演算をサポートしています。サポートしている演算を以下に示します。演算結果がMINYEARより小さくなったり、MAXYEARを超える場合はOverflowErrorを送出します。送出する可能性のある演算にはそのことも付記します。
算術演算 | 結果 |
---|---|
date2 = date1 + timedelta | date2は、date1からtimedelta.daysだけ日数が進んだ日付になる 例外:OverflowError |
date2 = date1 – timedelta | date2は、date1よりtimedelta.daysだけ前の日付になる 例外:OverflowError |
timedelta = date1 – date2 | 日数の差を表すtimedeltaオブジェクトになる |
dateオブジェクトは次の比較演算もサポートしています。不等号で異なる型との比較はTypeErrorを送出します。ただし、 比較相手に timetuple() 属性がある場合は、 代わりにNotImplemented を送出します。等号では異なる型との比較でも常にbool値を返します。
比較演算 | 結果 |
---|---|
date1 == date2 | date1とdate2が等しければTrue。そうでなければFalse |
date1 != date2 | date1とdate2が等しくなければTrue。そうでなければFalse |
date1 < date2 (またはdate1 > date2) | date1よりdate2が大きければTrue。そうでなければFalse 例外:TypeError または NotImplemented |
date1 <= date2 (またはdate1 >= date2) | date1とdate2が等しい、またはdate1よりdate2が大きければTrue。そうでなければFalse 例外:TypeError または NotImplemented |
dateオブジェクトの演算の例をいくつか示します。
>>> date1 = date(2023, 5, 3)
>>> date2 = date(2023, 5, 4)
# 等値性の比較
>>> date1 == date2
False
>>> date1 == date(2023, 5, 3)
True
>>> date1 != date2
True
# 等号は異なる型との比較でもbool値を返す
>>> date1 == 5
False
# 不等号での比較
>>> date1 < date2
True
>>> date1 <= date(2023, 5, 3)
True
# 不等号で異なる型との比較はTypeErrorを送出する
>>> date1 <= 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<=' not supported between instances of 'datetime.date' and 'int'
timeオブジェクトの解説
timeオブジェクトは1日の中の時刻を表します。1日は厳密に60*60*24秒であると仮定します。
timeオブジェクトは引数として、時、分、秒、マイクロ秒、tzinfoのサブクラスのインスタンスを渡して作成できます。
datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
すべての引数はオプションです。tzinfoのデフォルト値はNone、それ以外の引数のデフォルトは0です。
引数に指定できる値の範囲は以下の通りです。範囲外の引数を渡すとValueErrorが送出されます。
- 0 <= hour < 24
- 0 <= minute < 60
- 0 <= second < 60
- 0 <= microsecond < 1000000
- tzinfoはNoneまたはtzinfoのサブクラスのインスタンス
>>> from datetime import time
>>> t = time(1, 2, 3, 456789)
>>> t
datetime.time(1, 2, 3, 456789)
時、分、秒、マイクロ秒は属性として参照できます。
>>> t.hour
1
>>> t.minute
2
>>> t.second
3
>>> t.microsecond
456789
timeオブジェクトで表現できる最大値と最小値はクラス属性として定義されています。
>>> time.min
datetime.time(0, 0)
>>> time.max
datetime.time(23, 59, 59, 999999)
オブジェクトを生成するクラスメソッド — fromisoformat()
有効なISO 8601形式の文字列からtimeオブジェクトを作成することができます。それにはクラスメソッドfromisoformat()を使います。文字列の先頭のTはあってもなくても良く、秒の小数点以下の桁数は何桁あっても構わないが、6桁を超える桁数は切り捨てられます。
>>> time.fromisoformat('08:12:30')
datetime.time(8, 12, 30)
>>> time.fromisoformat('T08:12:30')
datetime.time(8, 12, 30)
>>> time.fromisoformat('T081230')
datetime.time(8, 12, 30)
>>> time.fromisoformat('081230')
datetime.time(8, 12, 30)
>>> time.fromisoformat('08:12:30.130843123')
datetime.time(8, 12, 30, 130843)
>>> time.fromisoformat('08:12:30,396')
datetime.time(8, 12, 30, 396000)
文字列へ変換する — isoformat()、strftime()
isoformat()メソッドは、ISO 8601形式の文字列を返します。
isoformat()メソッドにはオプションのtimespec引数を渡すことができます。timespec引数は時刻の出力形式を制御します。timespec引数を省略(あるいは’auto’を指定)した場合、microsecondが0と0以外で出力は次のように変わります。
- microsecondが0:HH:MM:SS
- microsecondが0以外:HH:MM:SS.ffffff
>>> t = time(8, 9, 30, 347000)
>>> t
datetime.time(8, 9, 30, 347000)
>>> t.isoformat()
'08:09:30.347000'
>>> t.replace(microsecond=0).isoformat()
'08:09:30'
timespec引数に渡せる値は’auto’の他に’hours’(HH形式)、’minutes’(HH:MM形式)、’seconds’(HH:MM:SS形式)、’milliseconds’(HH:MM:SS.sss形式)、’microseconds’(HH:MM:SS.mmmmmm形式)を指定できます。
>>> t.isoformat(timespec='hours')
'08'
>>> t.isoformat(timespec='minutes')
'08:09'
>>> t.isoformat(timespec='seconds')
'08:09:30'
>>> t.isoformat(timespec='milliseconds')
'08:09:30.347'
>>> t.isoformat(timespec='microseconds')
'08:09:30.347000'
strftime()メソッドは書式指定文字列にしたがって変換した文字列を返します。strftime()メソッドの詳細は後述します。
>>> t.strftime('%H-%M-%S')
'08-09-30'
timeオブジェクトの演算
timeオブジェクトではtimeオブジェクト同士での比較演算のみサポートしています。不等号で異なる型との比較はTypeErrorを送出します。等号では異なる型との比較でも常にbool値を返します。例外を送出する演算には、その例外も付記します。
time1 == time2 | time1とtime2が等しければTrue。そうでなければFalse |
time1 != time2 | time1とtime2が等しくなければTrue。そうでなければFalse。 |
time1 < time2 time1 > time2 | time1よりtime2が大きければTrue。そうでなければFalse。 例外:TypeError |
time1 <= time2 time1 >= time2 | time1とtime2が等しい、またはtime1よりtime2が大きければTrue。そうでなければFalse。 例外:TypeError |
次にtimeオブジェクトの比較演算の例を示します。
・>>> t1 = time(3, 30)
>>> t1
datetime.time(3, 30)
>>> t2 = time(7)
>>> t2
datetime.time(7, 0)
# 同値性の比較
>>> t1 == t2
False
>>> t1 == time(3, 30)
True
>>> t1 != t2
True
>>> t1 == 3
False
# 不等号での比較
>>> t1 < t2
True
>>> t1 >= t2
False
# 不等号で異なる型との比較はTypeErrorを送出する
>>> t1 < 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'datetime.time' and 'int'
datetimeオブジェクトの解説
datetimeオブジェクトは、dateとtimeオブジェクトの両方の情報が保持するオブジェクトです。dateオブジェクトと同様に、グレゴリオ暦で日付を表し、timeオブジェクトと同様に、1日が厳密に60*60*24秒であると仮定します。datetimeクラスはdateクラスのサブクラスです。
datetimeオブジェクトは引数に年、月、日、時、分、秒、マイクロ秒、tzinfoのサブクラスのインスタンスを渡して作成できます。
datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
year、month、dayの指定は必須です。引数の範囲は次の通りです。
- datetime.MINYEAR <= year <= datetime.MAXYEAR
- 1 <= month <= 12
- 1 <= day <= 指定された年での月の日数
- 0 <= hour < 24
- 0 <= minute < 60
- 0 <= second < 60
- 0 <= microsecond < 1000000
- tzinfoにはNoneまたはtzinfoのサブクラスのインスタンス
>>> from datetime import datetime
>>> dt = datetime(2022, 7, 4, 1, 2, 3, 456789)
>>> dt
datetime.datetime(2022, 7, 4, 1, 2, 3, 456789)
年、月、日、時、分、秒、マイクロ秒は属性としてアクセスできます。
>>> dt.year
2021
>>> dt.month
7
>>> dt.day
4
>>> dt.hour
1
>>> dt.hour
1
>>> dt.minute
2
>>> dt.second
3
>>> dt.microsecond
456789
datetimeオブジェクトで表現できる最大値と最小値はクラス属性として定義されています。
>>> datetime.min
datetime.datetime(1, 1, 1, 0, 0)
>>> datetime.max
datetime.datetime(9999, 12, 31, 23, 59, 59, 999999)
オブジェクトを生成するクラスメソッド — fromtimestamp()、fromisoformat()、fromisocalendar()
クラスメソッドfromtimestamp()は、time.time()が返すようなUNIX時間(POSIX タイムスタンプ)からローカルな日付と時刻を持つdatetimeオブジェクトを返します。
>>> datetime.fromtimestamp(time.time())
datetime.datetime(2023, 5, 27, 19, 19, 31, 209752)
引数のUNIX時間がシステムのC関数localtime()やgmtime()でサポートする範囲を超えるとOverflowErrorを送出することがあります。またlocaltime()やgmtime()が失敗した際はOSErrorを送出します。
有効なISO 8601形式の文字列からdatetimeオブジェクトを作成することもできます。それにはクラスメソッドfromisoformat()を使います。
>>> datetime.fromisoformat('2022-07-04')
datetime.datetime(2022, 7, 4, 0, 0)
>>> datetime.fromisoformat('20220704')
datetime.datetime(2022, 7, 4, 0, 0)
>>> datetime.fromisoformat('2022-07-04T08:12:30')
datetime.datetime(2022, 7, 4, 8, 12, 30)
>>> datetime.fromisoformat('20220704T081230')
datetime.datetime(2022, 7, 4, 8, 12, 30)
>>> datetime.fromisoformat('2022-W27-1T08:12:30.347')
datetime.datetime(2022, 7, 4, 8, 12, 30, 347000)
>>> datetime.fromisoformat('2022-07-04 08:12:30.347')
datetime.datetime(2022, 7, 4, 8, 12, 30, 347000)
クラスメソッドfromisocalendar()は、ISO 8601暦の年、週番号、日番号からdatetimeオブジェクトを生成します。
>>> datetime.fromisocalendar(2022, 27, 1)
datetime.datetime(2022, 7, 4, 0, 0)
現在日時のオブジェクトを取得 — today()、now()、utcnow()
クラスメソッドtoday()は、現在のローカルな日時のdatetimeオブジェクトを返します。
>>> today = datetime.today()
>>> today
datetime.datetime(2023, 5, 27, 19, 1, 26, 57297)
クラスメソッドnow()も同様に、現在のローカルな日時のdatetimeオブジェクトを返しますが、可能ならば time.time()で得られるより高い精度の時刻を提供します。また、now()には引数としてtzinfoのサブクラスのインスタンスを渡すこともできます。
>>> now = datetime.now()
>>> now
datetime.datetime(2023, 5, 27, 19, 1, 38, 358111)
一般にtoday()よりnow()を使った方が好ましいです。
クラスメソッドutcnow()はローカルな日時ではなく、UTCの現在日時のdatetimeオブジェクトを返します。返されるオブジェクトのtzinfo属性はNoneです。
>>> utcnow = datetime.utcnow()
>>> utcnow
datetime.datetime(2023, 5, 27, 10, 1, 53, 852997)
dateやtimeオブジェクトとの相互変換 — combine()、date()、time()
datetimeオブジェクトからdateオブジェクトやtimeオブジェクトを得ることができます。それにはdate()とtime()メソッドをそれぞれ使います。
>>> dt = datetime.now()
>>> dt
datetime.datetime(2023, 5, 27, 19, 4, 5, 596670)
>>> d = dt.date()
>>> d
datetime.date(2023, 5, 27)
>>> t = dt.time()
>>> t
datetime.time(19, 4, 5, 596670)
クラスメソッドcombine()は、反対にdateオブジェクトとtimeオブジェクトからdatetimeオブジェクトを作成します。
>>> datetime.combine(d, t)
datetime.datetime(2023, 5, 27, 19, 4, 5, 596670)
文字列へ変換する — isoformat()、ctime()、strftime()
isoformat()メソッドは、日時をISO 8601形式の文字列で返します。
isoformat()メソッドにはオプションのtimespec引数を渡すことができます。timespec引数は時刻の出力を制御します。timespec引数を省略(あるいは’auto’を指定)した場合、microsecondが0と0以外で出力は次のように変わります。
- microsecondが0:YYYY-MM-DDTHH:MM:SS
- microsecondが0以外:YYYY-MM-DDTHH:MM:SS.ffffff
>>> dt = datetime.datetime(2022, 7, 4, 8, 9, 30, 347000)
>>> dt
datetime.datetime(2022, 7, 4, 8, 9, 30, 347000)
>>> dt.isoformat()
'2022-07-04T08:09:30.347000'
>>> dt.replace(microsecond=0).isoformat()
'2022-07-04T08:09:30'
timespec引数に渡せる値は’auto’の他に’hours’(HH形式)、’minutes’(HH:MM形式)、’seconds’(HH:MM:SS形式)、’milliseconds’(HH:MM:SS.sss形式)、’microseconds’(HH:MM:SS.mmmmmm形式)を指定できます。
>>> dt.isoformat(timespec='hours')
'2022-07-04T08'
>>> dt.isoformat(timespec='minutes')
'2022-07-04T08:09'
>>> dt.isoformat(timespec='seconds')
'2022-07-04T08:09:30'
>>> dt.isoformat(timespec='milliseconds')
'2022-07-04T08:09:30.347'
>>> dt.isoformat(timespec='microseconds')
'2022-07-04T08:09:30.347000'
timespec引数以外に、オプションのsep引数 (デフォルトは’T’)もあります。これには1文字のセパレータを指定することができます。セパレータは日付と時刻の間に置かれます。
>>> dt.isoformat(sep=' ')
'2022-07-04 08:09:30.347000'
ctime()メソッドは、time.ctime()と同じ形式の文字列を返します。
>>> dt.ctime()
'Mon Jul 4 08:09:30 2022'
strftime()メソッドは書式指定文字列にしたがって変換した文字列を返します。strftime()メソッドの詳細は後述します。
>>> dt.strftime('%Y/%m/%d %H:%M')
'2022/07/04 08:09'
その他のインスタンスメソッド — replace()、timestamp()、weekday()、isoweekday()、isocalendar()
replace()メソッドは、引数に指定した年(year)、月(month)、日(day)、時(hour)、分(minute)、秒(second)、マイクロ秒(microsecond)を置換した新しいdateオブジェクトを返します。
>>> dt.replace(year=2001, month=8, day=12, hour=13, minute=8, second=37, microsecond=381)
datetime.datetime(2001, 8, 12, 13, 8, 37, 381)
この例ではキーワード引数の名前を示すために、year、month、day、hour、minute、second、microsecondを指定していますが、通常はこれらのうちのいくつかを指定します。省略した引数は値は元の値と同じになります。
timestamp()メソッドはdatetimeインスタンスに対応するUNIX時間(POSIX タイムスタンプ)返します。 返り値はtime.time()で返される値に近いfloat型の値です。
>>> dt.timestamp()
1656889770.347
weekday()とisoweekday()メソッドは、曜日を表す整数を返します。weekday()の場合は月曜日が0、日曜日は6です。isoweekday()の場合は月曜日が1、日曜日は7になります。
>>> dt.weekday()
0
>>> dt.isoweekday()
1
isocalendar()メソッドは、ISO 8601暦の名前付きタプルを返します。
>>> dt.isocalendar()
datetime.IsoCalendarDate(year=2022, week=27, weekday=1)
datetimeオブジェクトの演算
datetimeオブジェクトはいくつかの算術演算をサポートしています。サポートしている演算を以下に示します。演算結果がMINYEARより小さくなったり、MAXYEARを超える場合はOverflowErrorを送出します。送出する可能性のある演算にはその例外も付記します。
算術演算 | 結果 |
---|---|
dt2 = dt1 + timedelta | dt2はdt1からtimedeltaだけ進んだ日時になる 例外:OverflowError |
dt2 = dt1 – timedelta | dt2はdt1よりtimedeltaだけ戻った日時になる 例外:OverflowError |
timedelta = dt1 – dt2 | 日時の差を表すtimedeltaオブジェクトになる |
算術演算の例をいくつか示します。
>>> from datetime import datetime, timedelta
>>> dt1 = datetime(2023, 5, 10, 12, 0)
>>> dt2 = datetime(2023, 5, 9, 17, 30)
>>> td = timedelta(days=1, hours=2, minutes=30)
>>> str(dt1 + td)
'2023-05-11 14:30:00'
>>> str(dt1 - td)
'2023-05-09 09:30:00'
>>> str(dt1 - dt2)
'18:30:00'
datetimeオブジェクトは次の比較演算もサポートしています。不等号で異なる型との比較はTypeErrorを送出します。ただし、 比較相手に timetuple() 属性がある場合は、 NotImplemented が代わりに送出されます。等号では異なる型との比較でも常にbool値を返します。送出する可能性のある演算にはその例外も付記します。
比較演算 | 結果 |
---|---|
dt1 == dt2 | dt1とdt2が等しければTrue。そうでなければFalse |
dt1 != dt2 | dt1とdt2が等しくなければTrue。そうでなければFalse |
dt1 < dt2(またはdt1 > dt2) | dt1よりdt2の日時が後であればTrue。そうでなければFalse 例外:TypeError または NotImplemented |
dt1 <= dt2(またはdt1 >= dt2) | dt1とdt2が等しい、またはdt1よりdt2の日時が後であればTrue。そうでなければFalse 例外:TypeError または NotImplemented |
比較演算の例を以下に示します。
# 同値性の比較
>>> dt1 == dt2
False
>>> dt1 == dt2 + (dt1 - dt2)
True
>>> dt1 != dt2
True
>>> dt1 == 5
False
# 不等号での比較
>>> dt1 < dt2
False
>>> dt1 > dt2
True
# 不等号で異なる型との比較はTypeErrorを送出する
>>> dt1 < 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'datetime.datetime' and 'int'
strftime()とstrptime()の使い方
datetime、date、timeオブジェクトには、書式指定文字列にしたがって変換した文字列を返すstrftime()メソッドがあります。
反対にstrptime()メソッドは書式指定文字列にしたがって文字列を解析しdatetimeオブジェクト返します。strptime()メソッドはdatetimeクラスだけにあります。
書式指定子
strftime()とstrptime()メソッドで使用できる主な書式指定子には次のものがあります。
書式指定子 | 意味 | 例 |
---|---|---|
%Y | 年(4桁) | 2020, 2021, … |
%y | 年(下2桁) | 20,21, … |
%m | 月(1桁の場合は0が先行) | 01-12 |
%d | 日(1桁の場合は0が先行) | 01-31 |
%H | 時(24時間表記。1桁の場合は0が先行) | 00-23 |
%I | 時(12時間表記。1桁の場合は0が先行) | 01-12 |
%M | 分 | 00-59 |
%S | 秒 | 00-59 |
%f | マイクロ秒(6桁) | 000349 |
%p | ロケールのAM/PMを表す文字列 | AM, PM |
%a | ロケールの曜日の短縮形 | Sun, …, Sat |
%A | ロケールの曜日 | Sunday, …, Saturday |
%b | ロケールの月名の短縮形 | Jan, …, Dec |
%B | ロケールの月名 | January, …, December |
「’%Y-%m-%d’」のように文字列の中に書式指定子を埋め込みます。
フォーマットにしたがって文字列へ変換する — strftime()
strftime()メソッドは、引数に書式指定文字列を渡して呼び出します。書式指定文字列とは前述した書式指定子を埋め込んだ文字列です。書式指定文字列の書式指定子はオブジェクトの適切な値に変換されstrftime()メソッドから返されます。
strftime()メソッドはdatetime、date、timeオブジェクトのすべてで使用できます。
>>> dt = datetime.now()
>>> str(dt)
'2023-05-30 08:13:20.796720'
>>> d = dt.date()
>>> t = dt.time()
>>> dt.strftime('%Y年%m月%d日 %H時%M分%S秒')
'2023年05月30日 08時13分20秒'
>>> d.strftime('%Y/%m/%d')
'2023/05/30'
>>> t.strftime('%H:%M')
'08:13'
文字列を解析してdatetimeオブジェクトを生成する — strptime()
strftime()メソッドとは反対に、クラスメソッドstrptime()は文字列を書式指定文字列に従って解析しdatetimeオブジェクトを返します。strptime()はdatetimeクラスでのみ定義されています。書式は次のとおりです。
datetime.strptime(datetime_string, format)
datetime_string引数は解析する文字列で、formatが書式指定文字列です。
strptime()の例を以下に示します。
>>> from datetime import datetime
>>> datetime.strptime('2022年03月13日 21時41分52秒', '%Y年%m月%d日 %H時%M分%S秒')
datetime.datetime(2022, 3, 13, 21, 41, 52)
>>> datetime.strptime('foo_20220313-21-41-52', 'foo_%Y%m%d-%H-%M-%S')
datetime.datetime(2022, 3, 13, 21, 41, 52)
strptime()から取得できなかったdetetimeオブジェクトの属性はデフォルト値に設定されます。次の例はそのデフォルト値を示しています。すべての属性がstrptime()から値を得られなかったので、すべてデフォルト値(1900年1月1日0時0分0秒)に設定されます。
>>> default = datetime.datetime.strptime('', '')
>>> default.isoformat(timespec='microseconds')
'1900-01-01T00:00:00.000000'
次の例は、strptime()から取得できなかった一部の属性がデフォルト値に設定されることを示しています。
>>> d = datetime.datetime.strptime('2022年03月13日', '%Y年%m月%d日')
>>> d.isoformat(timespec='microseconds')
'2022-03-13T00:00:00.000000'
>>> t = datetime.datetime.strptime('21時41分52秒', '%H時%M分%S秒')
>>> t.isoformat(timespec='microseconds')
'1900-01-01T21:41:52.000000'
おわりに
Pythonには、日時を扱うモジュールとして、datetimeモジュールの他に前述したtimeモジュールがあります。timeモジュールは主にUNIX時間の時刻を扱うため、通常はdatetimeモジュールを使った方が便利です。
紛らわしいモジュールとしてcalendarモジュールというものもあります。これはcalコマンドのようなカレンダーを出力するための機能が主なもので、特定の日時を扱うものではありません。calendarモジュールは次の記事で解説していますので、興味があったらご参照ください。