時間計測には 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}')