時間計測には timeit モジュールまたは IPython の %timeit
機能が便利です:
%timeit x = 0; x = x + 1
14.7 ns ± 0.106 ns per loop (mean ± std. dev. of 7 runs, 100,000,000 loops each)
%timeit x = 0; x += 1
16.1 ns ± 0.00604 ns per loop (mean ± std. dev. of 7 runs, 100,000,000 loops each)
(あれ、x += 1
より x = x + 1
の方が若干速いんだ。)[2023-01-04 追記: M1 Mac mini 上の Python 3.11.1 で試したところ、どちらの時間も 12.3 ns ほどでした。]
ちなみに %%timeit
とすると複数行の計測ができます(対話型環境では終了は空行を二つほど打つ):
%%timeit x = 0 x += 1
15.7 ns ± 0.114 ns per loop (mean ± std. dev. of 7 runs, 100,000,000 loops each)
%timeit
の代わりに %time
とすれば1回の時間を計測できます。
標準モジュール time
はOSの機能に依存するようです。
time.time()
は現在時刻を1970年元旦からの秒数(float
型)で返します。time.sleep()
は指定した秒数(float
型)だけ休止します。
import time t1 = time.time() time.sleep(1.5) t2 = time.time() print(t2 - t1)
より精度の良い時間計測には time.perf_counter()
を使います。こちらは差だけに意味があります。
t1 = time.perf_counter() time.sleep(1.5) t2 = time.perf_counter() print(t2 - t1)
年月日時分秒で表した時刻:
time.localtime() # 現在時刻 time.localtime(t1) # 1970年頭からの秒数t1の時刻 time.strftime('%Y-%m-%d %H:%M:%S %Z', time.localtime()) # 'YYYY-MM-DD HH:MM:SS JST' time.strftime('%Y-%m-%d %H:%M:%S %Z', time.gmtime()) # 'YYYY-MM-DD HH:MM:SS UTC'
ファイルのタイムスタンプ:
import os p = os.stat("ファイルのパス") time.strftime('%Y-%m-%d %H:%M:%S %Z', time.localtime(p.st_mtime))
標準モジュール datetime
は time
と違ってOSに依存しません。
datetime.datetime
型は、年月日時分秒マイクロ秒を持つ構造体です:
import datetime datetime.datetime.now() # 現在時刻 datetime.datetime(年, 月, 日, 時, 分, 秒, μ秒) datetime.datetime.now(datetime.timezone.utc) # 同上(UTC) datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 'YYYY-MM-DD HH:MM:SS' f'{datetime.datetime.now():%Y-%m-%d %H:%M:%S}' # 上と同じ s = '2020-12-17 12:34:56' # 現在時刻 t = datetime.datetime.strptime(s, '%Y-%m-%d %H:%M:%S') t.timestamp() # Epochからの秒数(sが現地時刻のとき) t.replace(tzinfo=datetime.timezone.utc).timestamp() # sがUTCのとき t1 = datetime.datetime.now() # しばらく経って・・・ t2 = datetime.datetime.now() t2 - t1 # datetime.timedelta(seconds=秒, microseconds=μ秒) (t2 - t1).total_seconds() # 秒単位
例えば2019年5月1日で始まる32日分の配列:
import numpy as np import matplotlib.pyplot as plt t = [datetime.datetime(2019,5,1) + datetime.timedelta(days=i) for i in range(32)] rng = np.random.default_rng() x = np.cumsum(rng.standard_normal(32)) plt.plot(t, x) plt.xticks(rotation=20) plt.show()
別の表示法:
import matplotlib.dates as mdates fig, ax = plt.subplots() locator = mdates.AutoDateLocator() formatter = mdates.ConciseDateFormatter(locator) ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(formatter) ax.plot(t, x) plt.show()
dateutil - powerful extensions to datetime は pip install python-dateutil
でインストールできます。
from dateutil.parser import parse parse("1/6/21")
datetime.datetime(2021, 1, 6, 0, 0)
parse('Wed, 06 Jan 2021 12:54:19 +0900')
datetime.datetime(2021, 1, 6, 12, 54, 19, tzinfo=tzoffset(None, 32400))
NumPy の datetime64
はとても柔軟な日時型です。年(Y
)、月(M
)、週(W
)、日(D
)、時(h
)、分(m
)、秒(s
)、ミリ秒(ms
)などの単位で64ビット整数で表したものです。日時の起点は1970年元旦です。タイムゾーンは考えません。一番大きい単位 Y
を使った datetime64[Y]
型は ±9.2×1018 年まで表せます(宇宙の年齢は 1.38×1010 年ほど)。
import numpy as np np.datetime64("2019") # np.datetime64("2019", "Y") と同じ np.datetime64("2019-05") # np.datetime64("2019-05", "M") と同じ np.datetime64("2019-05-01") # np.datetime64("2019-05-01", "D") と同じ np.datetime64("2019-05-01 12:34:56") # np.datetime64("2019-05-01 12:34:56", "s") と同じ
日時の差は timedelta64()
で表します:
t = np.array([np.datetime64("2019-05-01") + np.timedelta64(i,"D") for i in range(32)])
これは次のようにも書けます:
t = np.arange(np.datetime64("2019-05-01"), np.datetime64("2019-06-02"))
pandas の Timestamp は NumPy の datetime64[ns]
(ナノ秒単位)に限定しているので、1677-09-21(pd.Timestamp(-2**63+808)
)から2262-04-11(pd.Timestamp(2**63-1)
)くらいまでしか扱えません(データの読み書き参照)。
import pandas as pd t = pd.to_datetime("2020-05-06") t = pd.to_datetime("2020年5月6日", format='%Y年%m月%d日') # 上と同じ t #==> Timestamp('2020-05-06 00:00:00') t.to_numpy() #==> numpy.datetime64('2020-05-06T00:00:00.000000000') t.to_pydatetime() #==> datetime.datetime(2020, 5, 6, 0, 0) t.timestamp() #==> 1588723200.0 # seconds since Epoch t.value #==> 1588723200000000000 # ns since Epoch t.strftime("%Y-%m-%d") #==> '2020-05-06' t.year #==> 2020 t.month #==> 5 t.day #==> 6 t.dayofweek #==> 2 # 水曜日 t + pd.Timedelta(1, "D") #==> Timestamp('2020-05-07 00:00:00') pd.to_datetime("2263-01-01") #==> TypeError OutOfBoundsDatetime pd.to_datetime("2263-01-01", errors="coerce") #==> NaT a = pd.date_range("2020-01-01", "2020-01-03") a #==> DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03'], dtype='datetime64[ns]', freq='D') np.max(a) #==> Timestamp('2020-01-03 00:00:00', freq='D')
format の形式については strftime() and strptime() Format Codes 参照。
Arrow: Better dates & times for Python は新しい日時ライブラリです。pip install arrow
でインストールできます。
Apache Arrow とは別物です。そちらの Python 版は PyArrow です。
import arrow t1 = arrow.now() t2 = arrow.utcnow() print(t1, t2) print(t2 - t1) print((t2 - t1).total_seconds())
2022-08-10T10:15:28.009095+09:00 2022-08-10T01:15:28.009191+00:00 0:00:00.000096 9.6e-05
t = arrow.get("2022-08-10 00+09:00") print(t) print(t.timestamp()) print(t.format()) print(t.format("YYYY-MM-DD HH:mm:ss.SSS"))
2022-08-10T00:00:00+09:00 1660057200.0 2022-08-10 00:00:00+09:00 2022-08-10 00:00:00.000
ファイルのタイムスタンプは次のようにして取得できます:
import os p = os.stat("ファイル名") print(f'{datetime.datetime.fromtimestamp(p.st_mtime):%Y-%m-%d %H:%M:%S}')