ill-identified diary

5 million yen salary expected.

[R] タイムゾーン変換

概要

  • Date-time オブジェクトのタイムゾーン変換がよく分からなかった.
  • 実はちゃんとリファレンスに書いてあった.

詳細

文字列を日付として取り込む場合, as.POSIX* を使う(strptime() 関数というのもある). さらにこのとき, タイムゾーンを指定すれば別の標準時間に変換して読み込んでくれる.

# タイムゾーン指定なしの場合ローカルのタイムゾーンになる.
as.POSIXlt(x="2015-01-11 00:00:01", format="%Y-%m-%d %H:%M:%S")
as.POSIXct(x="2015-01-11 00:00:01", format="%Y-%m-%d %H:%M:%S")

結果はいずれも

[1] "2015-01-11 JST"

タイムゾーンtz= で指定すると,

as.POSIXlt(x="2015-01-11 00:00:01", format="%Y-%m-%d %H:%M:%S", tz="Japan")
as.POSIXct(x="2015-01-11 00:00:01", format="%Y-%m-%d %H:%M:%S", tz="Japan")

結果はいずれも,

[1] "2015-01-11 00:00:01 JST"

では他のタイムゾーンにすると?

as.POSIXlt(x="2015-01-11 00:00:01", format="%Y-%m-%d %H:%M:%S", tz="Jamaica")
as.POSIXct(x="2015-01-11 00:00:01", format="%Y-%m-%d %H:%M:%S", tz="Jamaica")

結果はいずれも,

[1] "2015-01-11 00:00:01 EST"

なお, 指定できるタイムゾーンの名称は環境依存なので, OlsonNames() で使用可能な名称を確認したほうがいい. 日本の場合, JapanAsia/Tokyo が使用できるが, いずれも出力時は "JST" 表記になる.

問題はここからで, 一旦タイムゾーンを指定した時刻を別のタイムゾーンに変換するには? as.POSIXlt() で再度 tz= を指定してみた場合,

test <- as.POSIXlt(x="2015-01-01 00:00:01", format="%Y-%m-%d %H:%M:%S", tz="Japan")
as.POSIXlt(test, tz="Jamaica")

以下のように変わらないので不正解.

[1] "2015-01-01 00:00:01 JST"

正解は以下

as.POSIXlt(as.POSIXct(test, tz="Japan"),tz="Jamaica")
[1] "2014-12-31 10:00:01 EST"

一旦 as.POSIXct() にかけると, タイムゾーン表記が変わるが, 時刻は変わらない (言い換えるなら, 額面通りの時刻をそのタイムゾーンでの時刻とみなす). これにもう一度 as.POSIXlt() を通すと, 指定したタイムゾーンの時刻に変換される. なんとなく冗長な感じだが, これが正しい方法らしい. よそのサイト 有効なWikiNameではありません - RjpWiki では 『"POSIXct" オブジェクトはデータフレーム中で使うのにより便利であるが,"POSIXlt" オブジェクトはより可読性が高い.』というふうに書いてあったので, それが違いの本質かと誤解していたが, こういう用途があった.

という話, 実は公式マニュアルに書いてあった.

Character input is first converted to class "POSIXlt" by strptime: numeric input is first converted to "POSIXct". Any conversion that needs to go between the two date-time classes requires a time zone: conversion from "POSIXlt" to "POSIXct" will validate times in the selected time zone. One issue is what happens at transitions to and from DST, for example in the UK

as.POSIXct(strptime("2011-03-27 01:30:00", "%Y-%m-%d %H:%M:%S")) as.POSIXct(strptime("2010-10-31 01:30:00", "%Y-%m-%d %H:%M:%S"))

are respectively invalid (the clocks went forward at 1:00 GMT to 2:00 BST) and ambiguous (the clocks went back at 2:00 BST to 1:00 GMT).

英語でも面倒臭がらずに公式マニュアルをちゃんと読みましょう, というオチでした. "ct" が calendar time で, "lt" が local time らしいので, ct, lt の意味を覚えておけば混乱しないと思う. なお, Sys.time() 関数は POSIXct オブジェクトを返すので, as.POSIXlt(Sys.time(), tz="Jamaica") のようにすぐに別のタイムゾーンに変換できる.

参考文献