餡子付゛録゛

ソフトウェア開発ツールの便利な使い方を紹介。

前世紀風のRの日付処理

以前書いたエントリーを見直していて、操作を手早く紹介する例をつくっておきたくなりました。文字列型や数値型の日付データを、タイムゾーンUTCでのUNIX秒を保持するクラスPOSIXctか、日付構造体になっているリストPOSIXlt型に変換して操作して、文字列型に戻すだけの話なんですが、関数名をよく忘れるので。なお、最近はlubridateパッケージを使うのが一般的のようです。

# POSIXct → POSIXlt
now_ct <- Sys.time() # 現在時間を取得すると、POSIXct型で戻る
now_lt <- as.POSIXlt(now_ct)

# POSIXct or POSIXlt → numeric
now_unix_time <- as.numeric(now_ct)

# numeric → POSIXct, POSIXlt 
# tzの引数はOlsonNames()が返す値。tzを省略するとデフォルトのタイムゾーンになる
now_ct <- as.POSIXct(now_unix_time, origin="1970-01-01", tz="Japan")
now_lt <- as.POSIXlt(now_unix_time, origin="1970-01-01", tz="Japan")

# C言語のmktime風にPOSIXctに変換
now_ct <- ISOdate(1997, 4, 3, tz="Japan")
now_ct <- ISOdatetime(1997, 4, 3, 13, 34, 45, tz="Japan")
now_lt <- as.POSIXlt(now_ct)

# POSIXct or POSIXlt → 文字列
format(now_lt, "%Y/%m/%d %H:%M:%S") # helpはstrftimeを参照

# 文字列 → POSIXct
# formatを省略するとデフォルトのtryFormats(e.g. %Y/%m/%d)が試される
as.POSIXct("1997*4+3", format="%Y*%m+%d", tz="Japan")
as.POSIXlt("1997*4+3", format="%Y*%m+%d", tz="Japan")

# POSIXctと違いPOSIXltは30日後や100時間後のカレンダーの日付が得られる
# ただし$yearが{年-1900}(e.g. 2022年だと122),$monが{月-1}(e.g. 12月だと11)なのに注意
format(now_lt, "%Y/%m/%d %H:%M:%S")
now_lt$mday <- now_lt$mday + 30 # 30日後にセット
format(now_lt, "%Y/%m/%d %H:%M:%S")
now_lt$hours <- now_lt$hours + 100 # さらに100時間後にセット
format(now_lt, "%Y/%m/%d %H:%M:%S")

# roundで丸め処理ができる
round(as.POSIXlt("1997-4-3 12:34:56"), "mins")

# シーケンス生成もできる
seq(as.Date("2022/2/24"), as.Date("2022/10/13"), "weeks")
seq(as.POSIXlt("1997-4-3 12:34:56"), as.POSIXlt("1997-4-5 12:34:56"), "12 hours")

# 応用例:来年まであと何日?
now_lt <- as.POSIXlt(Sys.time())
# 今年(now_lt$year + 1900) + 1は来年
newyear_ct <- ISOdate(now_lt$year + 1900 + 1, 1, 1, tz="Japan")
# 差分をとる前にDate型にして端数を抑制
difftime(as.Date(newyear_ct), as.Date(now_lt), units="days")