Pythonのメモ(その2)datetimeのあれやこれや

Python

日付や時間は datetime ライブラリを使って処理しますが、この使い方をすぐ忘れてしまいます。また、1変数のときの扱い方はわかったけど、DataFrameで列全体を一括して処理したいときはどうすればいいのか、わからなくなるときが多々あります。まとめてメモしておきます。

1変数のとき

現在の日時を取得する

現在の日時

import datetime
dat_1 = datetime.datetime.now()
print(dat_1)
2021-11-19 17:01:21.154899

今日の日付

dat_2 = datetime.datetime.now().date()
# ..... または、
dat_2 = datetime.date.today()
print(dat_2)
2021-11-19

現在の時刻

dat_3 = datetime.datetime.now().time()
print(dat_3)
17:04:53.710288

「あの日時」を作る

あの日時

dat_4 = datetime.datetime(2021, 11, 19, 17, 5)            # 秒、マイクロ秒省略
print(dat_4, type(dat_4))
2021-11-19 17:05:00 <class 'datetime.datetime'>

あの日

dat_51 = datetime.datetime(2021, 11, 19)
# ..... または
dat_52 = datetime.date(2021, 11, 19)
print(dat_51, type(dat_51))
print(dat_52, type(dat_52))
2021-11-19 00:00:00 <class 'datetime.datetime'>
2021-11-19 <class 'datetime.date'>

datetimeオブジェクトは、dateオブジェクトに変換できる(日付だけにできる)

dat_41 = dat_4.date()
print(dat_41, type(dat_41))
2021-11-19 <class 'datetime.date'>

あの時刻

dat_6 = datetime.time(17, 5)                              # 秒、マイクロ秒省略
print(dat_6, type(dat_6))
17:05:00 <class 'datetime.time'>

datetimeオブジェクトは、timeオブジェクトに変換できる(時刻だけにできる)

dat_42 = dat_4.time()
print(dat_42, type(dat_42))
17:05:00 <class 'datetime.time'>

あの日、あの時刻を結合して、あの日時を作る

print(dat_41, type(dat_41))
print(dat_42, type(dat_42))

dat_7 = datetime.datetime.combine(dat_41, dat_42)
print(dat_7, type(dat_7))
2021-11-19 <class 'datetime.date'>
17:05:00 <class 'datetime.time'>
2021-11-19 17:05:00 <class 'datetime.datetime'>

年・月・日、時・分・秒・マイクロ秒を取得する

print(dat_1.year)
print(dat_1.month)
print(dat_1.day)
print(dat_1.hour)
print(dat_1.minute)
print(dat_1.second)
print(dat_1.microsecond)
2021
11
19
17
1
21
154899

日時/日付/時刻を文字列に変換する

str_1 = dat_1.strftime('%Y-%m-%d %H:%M:%S')                         # 日時
str_2 = dat_1.strftime('%Y-%m-%d')                                  # 日付
str_3 = dat_1.strftime('%H:%M:%S')                                  # 時刻
print(str_1)
print(str_2)
print(str_3)
2021-11-19 17:01:21
2021-11-19
17:01:21

文字列を日時/日付/時刻に変換する

dat_8  = datetime.datetime.strptime(str_1, '%Y-%m-%d %H:%M:%S')     # 日時
dat_9  = datetime.datetime.strptime(str_2, '%Y-%m-%d')              # 日付
dat_10 = datetime.datetime.strptime(str_3, '%H:%M:%S')              # 時刻
print(dat_8)
print(dat_9)
print(dat_10)
2021-11-19 17:01:21
2021-11-19 00:00:00
1900-01-01 17:01:21

となる。いずれもdatetimeオブジェクト。必要あれば、dat_9 は dateオブジェクト、dat_10 は timeオブジェクトに変換する。

dat_91  = dat_9.date()
dat_101 = dat_10.time()
print(dat_91)
print(dat_101)
2021-11-19
17:01:21

なお、str_1(’2021-11-19 17:01:21’)を直接、日付だけ、時刻だけに変換することはできない。以下はいずれもエラーになる。

datetime.datetime.strptime(str_1, '%Y-%m-%d')
datetime.datetime.strptime(str_1, '%H:%M:%S')

str_1を日付だけ、時刻だけにしたいときは、一旦、日時に変換してから、日付だけ、時刻だけにする。

datetime.datetime.strptime(str_1, '%Y-%m-%d %H:%M:%S').date()
datetime.datetime.strptime(str_1, '%Y-%m-%d %H:%M:%S').time()

或いは、str_1 は文字列だから、

datetime.datetime.strptime(str_1[:10], '%Y-%m-%d')
datetime.datetime.strptime(str_1[11:], '%H:%M:%S')

DataFrameで日時を扱うとき

事例

次のようなDataFrameを例にします。

import pandas as pd
df = pd.DataFrame([[2021,1,19,17,1,21], [2021,5,3,5,26,48], [2021,11,21,13,35,5]])
df.columns = ['y','m','d','H','M','S']
print(df)
      y   m   d   H   M   S
0  2021   1  19  17   1  21
1  2021   5   3   5  26  48
2  2021  11  21  13  35   5

年・月・日、時・分・秒を結合して日時を作る/文字列を日時に変換する

普通に文字列を結合してから、日時に変換してみました。pd.to_datetime() を使います。

df['str_01'] = df['y'].astype(str) +'-'+ df['m'].astype(str) +'-'+ df['d'].astype(str)
df['str_02'] = df['H'].astype(str) +':'+ df['M'].astype(str) +':'+ df['S'].astype(str)
df['str_0'] = df['str_01'] +' '+ df['str_02']
df['dat_1'] = pd.to_datetime(df['str_0'])
print(df[['str_0', 'dat_1']])
                str_0               dat_1
0   2021-1-19 17:1:21 2021-01-19 17:01:21
1    2021-5-3 5:26:48 2021-05-03 05:26:48
2  2021-11-21 13:35:5 2021-11-21 13:35:05

なお、str_01(日付の文字列)を to_datetime() に適用すれば、日付だけに変換される。

df['dat_11'] = pd.to_datetime(df['str_01'])
print(df['dat_11'])
0   2021-01-19
1   2021-05-03
2   2021-11-21
Name: dat_11, dtype: datetime64[ns]

一方、str_02(時刻の文字列)をこのまま適用すると、エラーになる。

df['dat_12'] = pd.to_datetime(df['str_02'])
OutOfBoundsDatetime: Out of bounds nanosecond timestamp: 1-01-01 17:01:21

formatを指定してやればエラーは解消する。

df['dat_12'] = pd.to_datetime(df['str_02'], format='%H:%M:%S')
print(df['dat_12'])
0   1900-01-01 17:01:21
1   1900-01-01 05:26:48
2   1900-01-01 13:35:05
Name: dat_12, dtype: datetime64[ns]

日時を日付だけ/時刻だけにする

日時を日付だけ、時刻だけにするには、dtアクセサを使って、.dt.date, .dt.time とする。

df['dat_2'] = df['dat_1'].dt.date
df['dat_3'] = df['dat_1'].dt.time
print(df[['dat_1', 'dat_2', 'dat_3']])
                dat_1       dat_2     dat_3
0 2021-01-19 17:01:21  2021-01-19  17:01:21
1 2021-05-03 05:26:48  2021-05-03  05:26:48
2 2021-11-21 13:35:05  2021-11-21  13:35:05

(別の方法)applyメソッド、lambda式を使う

与えられた文字列を日時に変換するなら、以上のように、to_datetime() による方法が簡単。でも、そもそも、年・月・日、時・分・秒が与えられるなら、lambda式をapplyメソッドで適用した方が回りくどくない。

df['dat_1a'] = df.apply(lambda x: datetime.datetime(x.y, x.m, x.d, x.H, x.M, x.S), axis=1)
df['dat_2a'] = df.apply(lambda x: datetime.date(x.y, x.m, x.d), axis=1)
df['dat_3a'] = df.apply(lambda x: datetime.time(x.H, x.M, x.S), axis=1)

print(df[['dat_1a','dat_2a','dat_3a']])
               dat_1a      dat_2a    dat_3a
0 2021-01-19 17:01:21  2021-01-19  17:01:21
1 2021-05-03 05:26:48  2021-05-03  05:26:48
2 2021-11-21 13:35:05  2021-11-21  13:35:05

日付と時刻を結合して日時にする

日付と時刻を一旦文字列にして結合し、その後、pd.to_datetime()で日時にする。

df['dat_4'] = pd.to_datetime(df['dat_2'].astype(str)+' '+df['dat_3'].astype(str))
print(df['dat_4'])
0   2021-01-19 17:01:21
1   2021-05-03 05:26:48
2   2021-11-21 13:35:05
Name: dat_4, dtype: datetime64[ns]

或いは、前項と同じようにapplyメソッド、lambda関数を使って、combineで結合する。

df['dat_4a'] = df.apply(lambda x: datetime.datetime.combine(x.dat_2, x.dat_3), axis=1)
print(df['dat_4a'])
0   2021-01-19 17:01:21
1   2021-05-03 05:26:48
2   2021-11-21 13:35:05
Name: dat_4a, dtype: datetime64[ns]

年・月・日、時・分・秒・マイクロ秒を取得する

dtアクセサを使う。

df['yy'] = df['dat_1'].dt.year
df['mm'] = df['dat_1'].dt.month
df['dd'] = df['dat_1'].dt.day
df['HH'] = df['dat_1'].dt.hour
df['MM'] = df['dat_1'].dt.minute
df['SS'] = df['dat_1'].dt.second
df['ms'] = df['dat_1'].dt.microsecond
print(df[['yy','mm','dd','HH','MM','SS','ms']])
     yy  mm  dd  HH  MM  SS  ms
0  2021   1  19  17   1  21   0
1  2021   5   3   5  26  48   0
2  2021  11  21  13  35   5   0

日時を文字列に変換する

.astype(str) で文字列に変換できる。

df['str_1'] = df['dat_1'].astype(str)
df['str_2'] = df['dat_2'].astype(str)
df['str_3'] = df['dat_3'].astype(str)
print(df[['str_1', 'str_2', 'str_3']])
                 str_1       str_2     str_3
0  2021-01-19 17:01:21  2021-01-19  17:01:21
1  2021-05-03 05:26:48  2021-05-03  05:26:48
2  2021-11-21 13:35:05  2021-11-21  13:35:05

或いは、.dt.strftime() で任意のフォーマットを指定する。

df['dat_21'] = df['dat_1'].dt.strftime('%Y-%m-%d')
df['dat_31'] = df['dat_1'].dt.strftime('%H:%M:%S')
print(df[['dat_21','dat_31']])
       dat_21    dat_31
0  2021-01-19  17:01:21
1  2021-05-03  05:26:48
2  2021-11-21  13:35:05
タイトルとURLをコピーしました