LoginSignup
0
0

np.datetime64のUnix時間とその浮動小数について

Last updated at Posted at 2023-11-02

np.datetime64の浮動小数としての扱いについて、本家サイトを見てもよくわからなかったので、挙動を確かめた。

結論

  • 場合によって数値のオーダーが勝手に変化するので危険
  • 第二引数でオーダーを強制的に指定するべし

np.datetime64とは?

pythonでの時刻を取り扱う規則?の一種で、numpyパッケージに組み込まれているもの。他には組み込みモジュールのdatetimeという組み込みモジュールやpandaspd.Timestampなどがある。

64は64bitなのだと思う。

Numbaではpandasはサポートされてないが、np.datetime64はサポートされている(ので使いたい)。

pandasほど受け入れる文字列は柔軟ではなく、ハイフン"-"で年月日、コロン":"で時分秒ミリ秒...を区切ることで、時刻を指定する。

import numpy as np
# numpyのバージョンは1.24.1

np.datetime64('1970-01-01 00')
# -> numpy.datetime64('1970-01-01T00','h')

np.datetime64('1970-01-01 00:00')
# -> numpy.datetime64('1970-01-01T00:00')

上記の2例、分を書くか時で止めるかで出力結果が少し異なる。

Unix時刻

上述の1970年1月1日0時UTC(世界標準時)はUnix時刻と呼ばれ、この時刻を基準に0と定義し、時間を相対的に表現する方法がある。この数値はdatetimepandasではTimestampと呼ばれる。故に、Unix時刻を浮動小数型へ変換すると0になる。

型の変換はnumpyにおいてはastypeメソッドが便利。

np.datetime64('1970-01-01 00').astype('float')
# -> 0.0

np.datetime64('1970-01-01 00:00').astype('float')
# -> 0.0

分まで書いても時まででも同じ結果となる。

このことにより、時刻を数列として扱いたいとき等に、このようにUnix秒へ変換すると、閏年の考慮や10進数/24進数/60進数の混在するプログラムを作らずに済むので便利。(追記:これは別にUnix秒へ変換せずともdatetimepd.Timestamp等をそのまま利用すれば良い。)

浮動小数(や整数)へ変換することで割り算など柔軟に使えるようになり、例えば時間内挿の計算に役立つ。

問題の処理

例えば、上記例より10時間ずらした値を見てみると、分まで書くか時までとするかで結果が異なる。(この仕様を知らず、泣かされた。。)

np.datetime64('1970-01-01 10').astype('float')
# -> 10.0

np.datetime64('1970-01-01 10:00').astype('float')
# -> 600.0

つまり、時間だけを指定すると単位は「時間」になり、分まで指定すると単位は「分」になる。10時間=600分。

1970年から遠ざかるほど、単位に比例してその差は増える。

np.datetime64('2024-01-01 00:00').astype('float')
# -> 28401120.0

np.datetime64('2024-01-01 00').astype('float')
# -> 473352.0

28401120.0/473352.0
# -> 60.0

特にpandasで生成したcsvファイルでは、フォーマットを指定しなかった場合、0時や0分など、最小単位が0となると省略されがちなので恐ろしい。

解決

一番最初の出力がヒントで、第二引数にD(日)やh(時)やm(分)やs(秒)を与えると、狙った時間単位を強制できる。それぞれUnix時間からの差分量を示す。

np.datetime64('2024-01-01 00', 's').astype('float')
# -> 1704067200.0

np.datetime64('2024-01-01 00', 'm').astype('float')
# -> 28401120.0

np.datetime64('2024-01-01 00', 'h').astype('float')
# -> 473352.0

np.datetime64('2024-01-01 00', 'D').astype('float')
# -> 19723.0

np.datetime64('2024-01-01 00', 'M').astype('float')
# -> 648.0

np.datetime64('2024-01-01 00', 'Y').astype('float')
# -> 54.0

大きい単位を選んだ場合、細かい時間の情報は失われるので注意。

np.datetime64('2024-01-01 00', 'h').astype('float')
# -> 473352.0

np.datetime64('2024-01-01 00:00:01', 'h').astype('float')
# -> 473352.0

np.datetime64('2024-01-01 00:59:59', 'h').astype('float')
# -> 473352.0
0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0