R の日付時刻オブジェクト

POSIXlt と POSIXct をよくわかっていなかったが、自分なりにまとめた。

test <- function(time.str, timezone) {
  # POSIXlt 型の変数
  time.lt <- strptime(time.str, format="%Y%m%d %H:%M:%OS", tz=timezone)
  print(time.lt)                        # 入力したままの年月日時刻・タイムゾーンが表示される
  print(paste(as.numeric(time.lt)))     # 協定世界時 1970年1月1日0時0分0秒からの経過秒になる
  print(strftime(time.lt))              # 入力したままの年月日時刻が表示される
  print(strftime(time.lt, tz="Egypt"))  # としてもエジプト時間にはならず、常に入力したままの年月日時刻が表示される
  print(paste0(1900 + time.lt$year, "/", 1 + time.lt$mon, "/", time.lt$mday)) # 年月日時を別々に取り出せる(入力まま)
  print(time.lt$isdst == 1)             # 夏時間かどうかわかる (夏時間がないタイムゾーンなら常にFALSE)
  cat("\n")
  
  # POSIXct 型の変数
  time.ct <- as.POSIXct(strptime(time.str, format="%Y%m%d %H:%M:%OS"), tz=timezone)
  print(time.ct)                        # 入力したたままの年月日時刻・タイムゾーンが表示される
  print(paste(as.numeric(time.ct)))     # 協定世界時 1970年1月1日0時0分0秒からの経過秒になる
  print(strftime(time.ct))              # タイムゾーンを指定しなければ自分のタイムゾーンの年月日時刻で表示される
  print(strftime(time.ct, tz=timezone)) # 入力したタイムゾーンを指定すれば入力したままの年月日時刻が表示される
  print(strftime(time.ct, tz="Egypt"))  # こうすればエジプト時間の年月日時刻で表示してくれる
  # print(paste0(1900 + time.ct$year, "/", 1 + time.ct$mon, "/", time.ct$mday)) # 年月日時を別々には取り出せない
  # print(time.ct$isdst == 1)           # 夏時間かどうかも取り出せない
  # POSIXct 型の変数は所望のタイムゾーンで as.POSIXlt に変換してから年月日時分秒曜日・夏時間かどうかを取り出す
  print(as.POSIXlt(time.ct, tz="Japan"))               # 日本時間で表示
  print(as.POSIXlt(time.ct, tz="GMT"))                 # 協定世界時で表示
  print(as.POSIXlt(time.ct, tz="EST5EDT"))             # アメリカ東部標準時で表示
  print(as.POSIXlt(time.ct, tz="EST"))                 # アメリカ東部標準時で表示 (夏時間なし)
  print(as.POSIXlt(time.ct, tz="EST5EDT")$isdst == 1)  # アメリカ夏時間かどうか
  cat("\n")
}

例えば以下のようになる。

例1

test("20150401 00:00:00.910", "GMT") # 協定世界時の2015年4月1日0時0分0.91秒
[1] "2015-04-01 00:00:00 GMT"
[1] "1427846400.91"
[1] "2015-04-01 00:00:00"
[1] "2015-04-01 00:00:00"
[1] "2015/4/1"
[1] FALSE

[1] "2015-04-01 00:00:00 GMT"
[1] "1427846400.91"
[1] "2015-04-01 09:00:00"
[1] "2015-04-01 00:00:00"
[1] "2015-04-01 02:00:00"
[1] "2015-04-01 09:00:00 JST"
[1] "2015-04-01 00:00:00 GMT"
[1] "2015-03-31 20:00:00 EDT"
[1] "2015-03-31 19:00:00 EST"
[1] TRUE

例2

test("20150331 20:00:00.910", "EST5EDT") # 同じ時点のアメリカ東部標準時表示
[1] "2015-03-31 20:00:00 EDT"
[1] "1427846400.91"
[1] "2015-03-31 20:00:00"
[1] "2015-03-31 20:00:00"
[1] "2015/3/31"
[1] TRUE

[1] "2015-03-31 20:00:00 EDT"
[1] "1427846400.91"
[1] "2015-04-01 09:00:00"
[1] "2015-03-31 20:00:00"
[1] "2015-04-01 02:00:00"
[1] "2015-04-01 09:00:00 JST"
[1] "2015-04-01 00:00:00 GMT"
[1] "2015-03-31 20:00:00 EDT"
[1] "2015-03-31 19:00:00 EST"
[1] TRUE
  • 協定世界時の2015年4月1日0時0分0.91秒=アメリカ東部標準時の2015年3月31日20時0分0.91秒は、協定世界時 1970年1月1日0時0分0秒から 1427846400.91 秒経った時点であり、POSIXlt も POSIXct もこれを認識している。
  • この時点はアメリカでは夏時間だが、例1の POSIXlt オブジェクトには「協定世界時」が貼り付いており、協定世界時に夏時間はないので、POSIXlt から取り出す「夏時間かどうか」はFALSEになっている。例2では「アメリカ東部標準時」として POSIXlt オブジェクトを生成されているので TRUE になっている。
  • 例1でも POSIXct を経由して「アメリカ東部標準時」の POSIXlt オブジェクトに変換した後「この時点はアメリカ東部標準時で夏時間かどうか」を問うとTRUEになっている。

まとめると、以下のように役割が違うようなので、用途に合わせ変換すればよさそう。

  • POSIXlt
    • エポック秒として取り出せる。
    • 別のタイムゾーンの時刻で表示することはできない。
    • 年月日、時分秒、曜日、夏時間かどうかをリスト要素として取り出せる。
  • POSIXct
    • エポック秒として取り出せる。
    • 任意のタイムゾーンの時刻で表示することができる。
    • 年月日、時分秒、曜日、夏時間かどうかをリスト要素として取り出すことはできない。

Rで協定世界時表示データからアメリカ夏時間かどうか判定したかったのでできてよかった。