通过`lubridate`引用将UTC日期/时间调整到不同的时区

时间:2017-03-27 22:18:17

标签: r date datetime data.table lubridate

我有一个data.table的UTC日期时间戳记记录跨越多个时区,我想创建一个新列,它将显示日期时间戳,但在每个观察的特定时区,由同一个表中的变量指定:

require("lubridate")
require("data.table")
dt <- data.table(A = 1:5, B = rep(ymd_hms("2016-03-24 17:15:12", tz = "UTC"), 5), timezone = c("America/Indiana/Vincennes", "Australia/North", "Pacific/Palau", "Antarctica/Macquarie", "Asia/Nicosia"))

我试图通过以下方式实现这一目标,但它似乎没有起作用:

dt[, B_local := with_tz(B, tz = timezone)]
dt
Error in as.POSIXlt.POSIXct(x, tz) : invalid 'tz' value

当我尝试在命令中添加by规范时,它更接近所需的输出,但是不正确,我认为不知何故是由于非唯一的日期时间和时区对,如此示例表,即:

dt[, B_local := with_tz(B, tz = timezone), by = .(B, timezone)]
dt
   A                   B                  timezone             B_local
1: 1 2016-03-24 17:15:12 America/Indiana/Vincennes 2016-03-24 19:15:12
2: 2 2016-03-24 17:15:12           Australia/North 2016-03-24 19:15:12
3: 3 2016-03-24 17:15:12             Pacific/Palau 2016-03-24 19:15:12
4: 4 2016-03-24 17:15:12      Antarctica/Macquarie 2016-03-24 19:15:12
5: 5 2016-03-24 17:15:12              Asia/Nicosia 2016-03-24 19:15:12

即使我将by = .(A)中的dt[, B_local := with_tz(B, tz = timezone), by = .(A)]更改为将表子行设置为每行,但输出与上述相同。

NB :我非常乐意使用lubridate之外的其他内容,但我更愿意在{{1}内工作为了提高效率,因为我有一个大型数据集。

1 个答案:

答案 0 :(得分:4)

这东西太乱了,很挑剔。我写了一个时区&#39; shifter&#39;在包RcppCCTZ中,作为基础CCTZ库使可行/可能。

一个巨大的警告:时区只出现在格式化的输出中,所以我在这里有一个解决方案,但目标输出现在是 text 已编辑:anytime()再解析一次时,当然可以POSIXct(在您当地的TZ中)。

另请注意,我使用anytime中的辅助函数来设置时间。

代码

suppressMessages({
    library("data.table")
    library("RcppCCTZ")
    library("anytime")
})

dt <- data.table(A = 1:5,
                 B = rep(utctime("2016-03-24 17:15:12", tz="UTC"), 5),
                 timezone = c("America/Indiana/Vincennes", "Australia/North",
                              "Pacific/Palau", "Antarctica/Macquarie",
                              "Asia/Nicosia"))
dt[ , newTime := format(toTz(B, "UTC", timezone), tz=timezone), by=A ]
dt[ , pt := anytime(newTime), by=A ]

输出

R> dt <- data.table(A = 1:5,
+                  B = rep(utctime("2016-03-24 17:15:12", tz="UTC"), 5),
+                  timezone = c("America/Indiana/Vincennes", "Australia/North",
+                               "Pacific/Palau", "Antarctica/Macquarie", 
+                               "Asia/Nicosia"))
R> dt[ , newTime := format(toTz(B, "UTC", timezone), tz=timezone), by=A ]
R> dt[ , pt := anytime(newTime), by=A ]
R> dt
   A                   B                  timezone             newTime                  pt
1: 1 2016-03-24 22:15:12 America/Indiana/Vincennes 2016-03-24 18:15:12 2016-03-24 18:15:12
2: 2 2016-03-24 22:15:12           Australia/North 2016-03-25 07:45:12 2016-03-25 07:45:12
3: 3 2016-03-24 22:15:12             Pacific/Palau 2016-03-25 07:15:12 2016-03-25 07:15:12
4: 4 2016-03-24 22:15:12      Antarctica/Macquarie 2016-03-25 09:15:12 2016-03-25 09:15:12
5: 5 2016-03-24 22:15:12              Asia/Nicosia 2016-03-25 00:15:12 2016-03-25 00:15:12
R>