RのSys.time()でミリ秒以下を表示する

by
カテゴリ:

Rで時刻を表示すると、デフォルトでは秒までしか表示されません。ログを管理するときに、ミリ秒以下も出せないと色々と不便なので、方法を調査しました。

time <- Sys.time()
print(time)
#> [1] "2024-12-24 06:54:23 JST"

?Sys.timeを確認すると、digits.secオプションで小数点何ケタまで表示するか調整できるとわかります(https://helpr.atusy.net/?q=Sys.time&pkg=base&topic=Sys.time)。ただし、精度はマイクロ秒まで(6ケタ)。

withr::with_options(list(digits.secs = 6), {
  print(time)
})
#> [1] "2024-12-24 06:54:23.650895 JST"

オプションを弄らずにやりたい場合はformat関数を使えばいい模様(?format.POSIXct https://helpr.atusy.net/?q=format.posix&pkg=base&topic=format.POSIXct)。たとえば3ケタまで表示したいなら以下のとおり。

format(time, "%Y-%m-%d %H:%M:%OS3 %Z")
#> [1] "2024-12-24 06:54:23.650 JST"

こちらも精度はマイクロ秒(6ケタ)まで。

format(time, "%Y-%m-%d %H:%M:%OS6 %Z")
#> [1] "2024-12-24 06:54:23.650895 JST"
format(time, "%Y-%m-%d %H:%M:%OS7 %Z")
#> [1] "2024-12-24 06:54:23.650895 JST"

6ケタ以上表示したい場合は、Sys.time()の返り値がPOSIXctクラスで、1970-01-01 00:00:00 UTCを基準とした秒単位のデータなことが利用できそう。

structure(0L, class = c("POSIXct", "POSIXt"))
#> [1] "1970-01-01 09:00:00 JST"

実際、以下のようにして、ナノ秒(少数部分9ケタ)を取り出すことができる(何桁までとれるかはOS依存)。

format(as.numeric(time) %% 1, digits = 9)
#> [1] "0.650895119"

といわけで、あとはよしなに整形すればよい。

digits <- 9
paste0(
  format(time, "%Y-%m-%dT%H:%M:%S", tz = "UTC"),
  format(as.numeric(time) %% 1, digits = digits) |> substr(2, digits + 2),
  "Z"
)
#> [1] "2024-12-23T21:54:23.650895119Z"

モチベのログの話に戻るとloggerパッケージは、時刻のフォーマットを弄る仕組みを提供していないので、オプションを変更するしかなさそう。つらい。タイムゾーンの調整とかもできないので、PRの機運ですね。

ENJOY!