Python基礎12:日付型および時間型の操作(datetime)
0.概要
Pythonの標準ライブラリであるdatetimeを使用して日付型や時間型の操作をします。標準ライブラリのため環境構築などは不要です。
1.datetimeの概要
1-1.UNIX時間と日本標準時
時刻表現には複数種類あり、Pythonではtimeモジュール:UNIX、datetimeモジュール:日本標準時 (JST)(※正確には使用している環境により異なる)となります。
[IN]
import datetime
import time
#UNIX時間
time_unix = time.time() #UNIX時間:1970年1月1日0時0分0秒を基準とした秒数
print(f'UNIX時間: {time_unix}, データ型: {type(time_unix)}')
#非UNIX時間
now = datetime.datetime.now() #非UNIX時間
print(f'非UNIX時間: {now}, データ型: {type(now)}')
[OUT]
UNIX時間: 1673854550.6812384, データ型: <class 'float'>
非UNIX時間: 2023-01-16 16:35:50.681238, データ型: <class 'datetime.datetime'>
1-2.datetimeのオブジェクト
datetimeライブラリには複数のオブジェクトがあります。使用は用途に分けて使い分けます。
【datetime型:日付と時刻を組み合わせたもの】
[datetime オブジェクト]
datetime.datetime(year, month, day,
hour=0, minute=0, second=0, microsecond=0,
tzinfo=None, *, fold=0)
【date型:日付情報のみ(グレゴリオ暦 ベース)】
[date オブジェクト]
datetime.date(year, month, day)
【time型:日付とは独立した、特定の時間を扱う】
[time オブジェクト]
datetime.time(hour=0, minute=0, second=0, microsecond=0,
tzinfo=None, *, fold=0)
【tzinfo型:タイムゾーン情報を扱う】
[tzinfo オブジェクト]
datetime.tzinfo
【timezone型:タイムゾーンを扱う】
[timezone オブジェクト]
datetime.timezone(offset, name=None)
【timedelta型:日付・時刻の差分を扱う】
[timedelta オブジェクト]
datetime.timedelta(days=0, seconds=0,
microseconds=0, milliseconds=0,
minutes=0, hours=0, weeks=0)
各オブジェクトの実行例は下記の通りです。
[IN]
import datetime
#datetimeオブジェクト:日付と時間の両方を持つオブジェクト
now = datetime.datetime.now()
print(f'datetime.datetime.now():{now}')
print(f'datetime.datetime.now():{type(now)}')
#dateオブジェクト:日付情報のみ
today = datetime.date.today()
print(f'datetime.date.today():{today}')
print(f'datetime.date.today():{type(today)}')
#timeオブジェクト:特定の時間
time = datetime.time()
print(f'datetime.time():{time}')
print(f'datetime.time():{type(time)}')
#tzinfoオブジェクト:タイムゾーン情報
tzinfo = datetime.tzinfo()
print(f'datetime.tzinfo():{tzinfo}')
print(f'datetime.tzinfo():{type(tzinfo)}')
#timezoneオブジェクト:タイムゾーン情報
timezone = datetime.timezone(datetime.timedelta(hours=9))
print(f'datetime.timezone():{timezone}')
print(f'datetime.timezone():{type(timezone)}')
#timedeltaオブジェクト:時間の差分
timedelta = datetime.timedelta(days=1)
print(f'datetime.timedelta():{timedelta}')
print(f'datetime.timedelta():{type(timedelta)}')
[OUT]
datetime.datetime.now():2023-01-16 17:10:31.562619
datetime.datetime.now():<class 'datetime.datetime'>
datetime.date.today():2023-01-16
datetime.date.today():<class 'datetime.date'>
datetime.time():00:00:00
datetime.time():<class 'datetime.time'>
datetime.tzinfo():<datetime.tzinfo object at 0x0000019DE61D9760>
datetime.tzinfo():<class 'datetime.tzinfo'>
datetime.timezone():UTC+09:00
datetime.timezone():<class 'datetime.timezone'>
datetime.timedelta():1 day, 0:00:00
datetime.timedelta():<class 'datetime.timedelta'>
2.日付・時刻(datetime)
2-1.日付・時刻の作成:datetime
datetimeオブジェクトでdatetimeを作成します。作成方法は①現在の時間をメソッドで取得、②手入力 があります。手入力の場合は下記のオブジェクト情報から引数に必要な情報を入力します。
[datetime オブジェクト]
datetime.datetime(year, month, day,
hour=0, minute=0, second=0, microsecond=0,
tzinfo=None, *, fold=0)
[date オブジェクト]
datetime.date(year, month, day)
[time オブジェクト]
datetime.time(hour=0, minute=0, second=0, microsecond=0,
tzinfo=None, *, fold=0)
下記に手入力とメソッド方式の2つを記載しました。引数が無いものは0が入力されます。メソッドでは”協定世界時 (UTC)と日本標準時 (JST)”を選択して時刻取得可能です。
[IN]
import datetime
today_date = datetime.datetime(2023,1,16)
today_detail = datetime.datetime(2023, 1, 16, 17, 30, 45)
print(today_date)
print(today_detail)
[OUT]
2023-01-16 00:00:00
2023-01-16 17:30:45
[IN]
import datetime
#日本標準時(JST):Japan Standard Time
now = datetime.datetime.now()
today = datetime.datetime.today()
#協定世界時 (UTC) :Coordinated Universal Time
utcnow = datetime.datetime.utcnow()
print(f'now:{now}')
print(f'today:{today}')
print(f'utcnow:{utcnow}')
[OUT]
now:2023-01-16 17:16:10.740619
today:2023-01-16 17:16:10.740619
utcnow:2023-01-16 08:16:10.740619
2-2.datetimeオブジェクトの属性
各種オブジェクト(datetime, date, time)には下記の属性があります。その他の属性は公式Docsをご確認ください。
[IN]
import datetime
now = datetime.datetime.now()
print(f'データ型: {type(now)}', end='\n\n')
print(f'now: {now}')
print(f'now.year: {now.year}')
print(f'now.month: {now.month}')
print(f'now.day: {now.day}')
print(f'now.hour: {now.hour}')
print(f'now.minute: {now.minute}')
print(f'now.second: {now.second}')
print(f'now.microsecond: {now.microsecond}')
print(f'now.weekday(): {now.weekday()}') #曜日を数値で返す(月曜日が0、日曜日が6)
print(f'now.isoweekday(): {now.isoweekday()}') #曜日を数値で返す(月曜日が1、日曜日が7)
print(f'now.tzinfo: {now.tzinfo}')
print(f'now.date(): {now.date()}')
print(f'now.time(): {now.time()}')
[OUT]
データ型: <class 'datetime.datetime'>
now: 2023-01-16 16:57:28.323268
now.year: 2023
now.month: 1
now.day: 16
now.hour: 16
now.minute: 57
now.second: 28
now.microsecond: 323268
now.weekday(): 0
now.isoweekday(): 1
now.tzinfo: None
now.date(): 2023-01-16
now.time(): 16:57:28.323268
データ型: <class 'datetime.date'>
[IN]
today = datetime.date.today()
print(f'データ型: {type(today)}', end='\n\n')
print(f'today: {today}')
print(f'today.year: {today.year}')
print(f'today.month: {today.month}')
print(f'today.day: {today.day}')
print(f'today.weekday(): {today.weekday()}') #曜日を数値で返す(月曜日が0、日曜日が6)
print(f'today.isoweekday(): {today.isoweekday()}') #曜日を数値で返す(月曜日が1、日曜日が7
print(f'today.isoformat(): {today.isoformat()}')
time = datetime.time()
print(f'データ型: {type(time)}', end='\n\n')
print(f'time: {time}')
print(f'time.hour: {time.hour}')
print(f'time.minute: {time.minute}')
print(f'time.second: {time.second}')
print(f'time.microsecond: {time.microsecond}')
print(f'time.tzinfo: {time.tzinfo}')
print(f'time.isoformat(): {time.isoformat()}')
print(f'time.strftime("%H:%M:%S"): {time.strftime("%H:%M:%S")}')
[OUT]
データ型: <class 'datetime.date'>
today: 2023-01-16
today.year: 2023
today.month: 1
today.day: 16
today.weekday(): 0
today.isoweekday(): 1
today.isoformat(): 2023-01-16
データ型: <class 'datetime.time'>
time: 00:00:00
time.hour: 0
time.minute: 0
time.second: 0
time.microsecond: 0
time.tzinfo: None
time.isoformat(): 00:00:00
time.strftime("%H:%M:%S"): 00:00:00
3.日付・時刻の計算
3-1.日付・時刻の加算:timedelta
”今日からX日後の日付”などを計算する場合、普通の数値だとエラーが発生します。datetime型の値を加算する場合はtimedeltaオブジェクトを使用します。なお下記オブジェクト情報の通り、timedeltaにはdate()の計算しかできず、month, yearを計算したい場合は別の手法が必要です。
[timedelta オブジェクト]
datetime.timedelta(days=0, seconds=0,
microseconds=0, milliseconds=0,
minutes=0, hours=0, weeks=0)
それでは下記に実行例を示します。
[IN]
import datetime
today = datetime.datetime.today()
print(today)
dayaftertom = today+datetime.timedelta(days=2)
print(dayaftertom)
[OUT]
2023-01-16 17:30:06.191252
2023-01-18 17:30:06.191252
[IN]
import datetime
today = datetime.datetime.today()
today+5
[OUT]
TypeError: unsupported operand type(s) for +: 'datetime.datetime' and 'int'
3-2.datetime同士の差分
日付同士の差分に関しては通常の引き算と同じ数式で実施できます。なお足し算に関しては"datetime"と"timedelta"であればできますがdatime同士ではエラーが発生します。
[IN]
date1 = datetime.datetime(2023, 1, 1, 13, 30, 45)
date2 = datetime.datetime(2023, 1, 16, 17, 30, 45)
diff_date = date2 - date1
print(diff_date)
print(type(diff_date))
[OUT]
15 days, 4:00:00
<class 'datetime.timedelta'>
3-3.datetimeの比較
datetimeの比較はPythonの比較演算子を使用することで実施できます。
[IN]
date1 = datetime.datetime(2023, 1, 1, 13, 30, 45)
date2 = datetime.datetime(2023, 1, 16, 17, 30, 45)
print(f'date1==date2:{date1==date2}')
print(f'date1!=date2:{date1!=date2}')
print(f'date1>date2:{date1>date2}')
print(f'date1<date2:{date1<date2}')
[OUT]
date1==date2:False
date1!=date2:True
date1>date2:False
date1<date2:True
4.datetimeの型変換:一般
4-1.UNIX時間の変換・逆変換
UNIX時間の変換・逆変換は下記を使用します。なおUNIX変換後の値はfloat型になることに注意が必要です。
UNIXへの変換(datetime->UNIX):timestamp()
逆変換(UNIX->datetime):fromtimestamp(<UNIXの値>)
[IN]
import datetime
today = datetime.datetime.today()
today_unix = today.timestamp()
print(f'today: {today}, データ型: {type(today)}')
print(f'UNIX時間: {today_unix}, データ型: {type(today_unix)}')
today_non_unix = datetime.datetime.fromtimestamp(today_unix)
print(f'非UNIX時間: {today_non_unix}, データ型: {type(today_non_unix)}')
[OUT]
today: 2023-01-16 17:25:00.743619, データ型: <class 'datetime.datetime'>
UNIX時間: 1673857500.743619, データ型: <class 'float'>
非UNIX時間: 2023-01-16 17:25:00.743619, データ型: <class 'datetime.datetime'>
5.datetimeと文字列型の変換
Pandasなどでテーブルデータを抽出すると(ちゃんと日付をparseできないことが多いため)日付が文字列で取得されることがよくあります。ここでは文字列とdatetime型の変換を理解します。
変換方法は”strftime”と”strptime”があり、下記特徴があります。
それぞれのメソッドでformat(日付の書式)指定が必要になりますが、formatの参考例は下記の通りです。
5-1.datetime->文字列:strftime()
datetime型を文字列型に変換する場合は”datetime.strftime(format)”を使用します。
[IN]
import datetime
now = datetime.datetime.now()
now_str = now.strftime('%Y-%m-%d %H:%M:%S')
print(f'now: {now}, データ型: {type(now)}')
print(f'now_str: {now_str}, データ型: {type(now_str)}', end='\n\n')
#datetimeオブジェクトを文字列に変換
print(now.strftime('%Y-%m-%d'))
print(now.strftime('%m/%d/%Y'))
print(now.strftime('%d.%m.%Y'))
print(now.strftime('%Y%m%d'))
print(now.strftime('%A, %B %d, %Y'))
print(now.strftime('%B %d, %Y'))
print(now.strftime('%d-%m-%Y'))
print(now.strftime('%Y.%m.%d'))
print(now.strftime('%Y%m%d'))
print(now.strftime('%m%d%Y'))
print(now.strftime('%A %d %B %Y'))
print(now.strftime('%d %A %B %Y'))
print(now.strftime('%d/%m/%Y'))
print(now.strftime('%B %d, %Y'))
print(now.strftime('%A, %d %B %Y'))
[OUT]
now: 2023-01-16 18:14:31.091559, データ型: <class 'datetime.datetime'>
now_str: 2023-01-16 18:14:31, データ型: <class 'str'>
2023-01-16
01/16/2023
16.01.2023
20230116
Monday, January 16, 2023
January 16, 2023
16-01-2023
2023.01.16
20230116
01162023
Monday 16 January 2023
16 Monday January 2023
16/01/2023
January 16, 2023
Monday, 16 January 2023
5-2.文字列->datetime:strptime()
文字列をdatetime型に変換するには”datetime.strptime(<date_string>, <format>)”を使用します。つまり文字列に合わせて書式も引数に渡す必要があります。
[IN]
print(datetime.datetime.strptime('2023-01-16', '%Y-%m-%d'))
print(datetime.datetime.strptime('01/16/2023', '%m/%d/%Y'))
print(datetime.datetime.strptime('16.01.2023', '%d.%m.%Y'))
print(datetime.datetime.strptime('20230116', '%Y%m%d'))
print(datetime.datetime.strptime('Monday, January 16, 2023', '%A, %B %d, %Y'))
print(datetime.datetime.strptime('January 16, 2023', '%B %d, %Y'))
print(datetime.datetime.strptime('16-01-2023', '%d-%m-%Y'))
print(datetime.datetime.strptime('2023.01.16', '%Y.%m.%d'))
print(datetime.datetime.strptime('20230116', '%Y%m%d'))
print(datetime.datetime.strptime('01162023', '%m%d%Y'))
print(datetime.datetime.strptime('Monday 16 January 2023', '%A %d %B %Y'))
print(datetime.datetime.strptime('16 Monday January 2023', '%d %A %B %Y'))
print(datetime.datetime.strptime('16/01/2023', '%d/%m/%Y'))
print(datetime.datetime.strptime('January 16, 2023', '%B %d, %Y'))
print(datetime.datetime.strptime('Monday, 16 January 2023', '%A, %d %B %Y'))
[OUT]
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
2023-01-16 00:00:00
文字列に合わせて書式も渡すのがひと手間の方は専用の関数を作成しても良いかもしれません。
6.おまけ
datetimeとは関係ないですが、日付を扱うモジュールを紹介します。
6-1.calenderモジュール
Pythonではカレンダーを表示するモジュールとしてcalenderライブラリがあります。
[IN]
import calendar
calendar.setfirstweekday(calendar.SUNDAY) #月曜日を始まりとする
print(type(calendar.month(2023, 1)))
print(calendar.month(2023, 1)) #2023年1月のカレンダーを表示
[OUT]
<class 'str'>
January 2023
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
参考記事
あとがき
時系列とかでは必須の技術なのでとりあえずまとめ