🕐

Unix時間とWindowsのFILETIMEを変換する

2024/05/26に公開

はじめに

Unix系では1970-01-01 00:00:00 UTC(Unixエポック)からの経過秒数で表されるUnix時間が主に使われていますが、Windowsでは1601-01-01 00:00:00 UTC(NTタイムエポック)からの100ナノ秒単位の経過秒数で表されるFILETIMEが使われています。

今回はこの2つのタイムスタンプの変換方法についてまとめたいと思います。

前提条件

  • time_tなどで表される秒単位のUnix時間のデータ型は64ビット符号付き整数型とします。
  • timespecなどで表されるナノ秒単位のUnix時間のデータ型は128ビット符号付き整数型とします。
  • FILETIMEのデータ型は64ビット符号なし整数型とします。
  • 整数同士の割り算の結果は小数点以下を切り捨てた整数値とします。

Unix時間 to FILETIME

Unix時間からFILETIMEへの変換では、Unix時間がNTタイムエポックからFILETIMEの最大値の+60056-05-28 05:36:10.955161500 UTCに収まらない可能性があるので、範囲内かを確認する処理が必要になります。

秒単位

秒単位のUnix時間をFILETIMEに変換するには以下のような処理を行います。

  1. Unix時間が1,833,029,933,770(FILETIMEの最大値)以下であることを確認する。
  2. Unix時間にUnixエポックとNTタイムエポックの差の秒数の11,644,473,600を足す。
  3. 2の結果が正の数であることを確認する。
  4. 2の結果に10,000,000を掛けて100ナノ秒単位にする。

https://github.com/sorairolake/nt-time/blob/v0.7.0/src/file_time/unix_time.rs#L94-L104

ナノ秒単位

ナノ秒単位のUnix時間をFILETIMEに変換するには以下のような処理を行います。

  1. Unix時間が1,833,029,933,770,955,161,500(FILETIMEの最大値)以下であることを確認する。
  2. Unix時間にUnixエポックとNTタイムエポックの差のナノ秒数の11,644,473,600,000,000,000を足す。
  3. 2の結果が正の数であることを確認する。
  4. 2の結果を100で割って100ナノ秒単位にする。

https://github.com/sorairolake/nt-time/blob/v0.7.0/src/file_time/unix_time.rs#L137-L148

FILETIME to Unix時間

64ビット符号付き整数型のUnix時間ではおよそ紀元前3000億年からおよそ3000億年の範囲を表すことができるので、FILETIMEからUnix時間への変換は常に成功します。
ナノ秒単位のUnix時間の場合もこの変換は128ビット符号付き整数型に収まるので同様です。

秒単位

FILETIMEを秒単位のUnix時間に変換するには以下のような処理を行います。

  1. FILETIMEを10,000,000で割って秒単位にする。
  2. 1の結果からUnixエポックとNTタイムエポックの差の秒数の11,644,473,600を引く。

https://github.com/sorairolake/nt-time/blob/v0.7.0/src/file_time/unix_time.rs#L30-L34

ナノ秒単位

FILETIMEをナノ秒単位のUnix時間に変換するには以下のような処理を行います。

  1. FILETIMEに100を掛けてナノ秒単位にする。
  2. 1の結果からUnixエポックとNTタイムエポックの差のナノ秒数の11,644,473,600,000,000,000を引く。

https://github.com/sorairolake/nt-time/blob/v0.7.0/src/file_time/unix_time.rs#L57-L59

まとめ

Unix時間とFILETIMEの変換方法についてまとめました。
今回は64ビット符号付き整数型の秒単位のUnix時間と128ビット符号付き整数型のナノ秒単位のUnix時間を扱いましたが、2038年問題で知られている古い32ビット符号付き整数型の秒単位のUnix時間の場合はFILETIMEからUnix時間への変換が失敗する可能性がある[1]など、データ型のサイズによって変換が常に成功するか失敗する可能性があるかが変化することに注意してください。

脚注
  1. FILETIMEが1901-12-13 20:45:52 UTCから2038-01-19 03:14:07 UTCに収まらない日時を表している場合に失敗します。 ↩︎

GitHubで編集を提案

Discussion