尝试反向转换时区向量

Trying to reverse-convert a vector of time zones

我有这个时间戳数据库 (AlertTime),并且我知道它们在哪个时区 (TimeZone)。我知道如何将这些日期设置为 POSIXCT 或者如果它们都是 UTC,但我正在努力将它们标识为它们的本地时间戳,因为大多数函数不接受 tz 的向量。

我确实需要格式正确的本地时间戳 (AlertTimeLocal) 和 UTC 等效时间 (AlertTimeUTC)。

AlertTime               TimeZone                AlertTimeLocal (desired)  AlertTimeUTC (desired)
11 May 2020, 06:22 PM   America/Denver          2020-05-11 18:22:00 MDT   2020-05-12 00:22:00 MDT
11 MAY 2020, 04:11 AM   America/Los_Angeles     2020-05-11 04:11:00 PDT   2020-05-11 11:11:00 UTC
10 MAY 2020, 03:38 PM   America/Chicago         2020-05-10 15:38:00 CDT   2020-05-10 20:38:00 CDT

我正在使用这段代码,但它似乎不再执行任何操作:

FreshAir$AlertTimeLocal <- mapply(function(x,y) {format(x, tz=y, usetz=TRUE)}, FreshAir$AlertTime, FreshAir$TimeZone)

将所有 RAW 时间戳设置为 UTC,然后将它们转换为相反方向的等效时区是否是一个 hacky 解决方案?

我们可以使用 lubridate

中的 force_tzs
library(lubridate)
library(dplyr)
df1 %>%
    mutate(AlertTimeLocal = dmy_hm(AlertTime), 
           AlertTimeUTC = force_tzs(AlertTimeLocal, tzones = TimeZone))
# AlertTime            TimeZone      AlertTimeLocal        AlertTimeUTC
#1 11 May 2020, 06:22 PM      America/Denver 2020-05-11 18:22:00 2020-05-12 00:22:00
#2 11 MAY 2020, 04:11 AM America/Los_Angeles 2020-05-11 04:11:00 2020-05-11 11:11:00
#3 10 MAY 2020, 03:38 PM     America/Chicago 2020-05-10 15:38:00 2020-05-10 20:38:00

更新

如果我们需要存储为单独的时区,我们可以使用 list

library(purrr)
df2 <- df1 %>%
         mutate(AlertTime2 = dmy_hm(AlertTime), 
         AlertTimeUTC = force_tzs(AlertTime2, tzones = TimeZone), 
         AlertTimeLocal = map2(AlertTime2, TimeZone, ~ force_tz(.x, tzone = .y))) 


df2$AlertTimeLocal
#[[1]]
#[1] "2020-05-11 18:22:00 MDT"

#[[2]]
#[1] "2020-05-11 04:11:00 PDT"

#[[3]]
#[1] "2020-05-10 15:38:00 CDT"

数据

df1 <- structure(list(AlertTime = c("11 May 2020, 06:22 PM",
       "11 MAY 2020, 04:11 AM", 
"10 MAY 2020, 03:38 PM"), TimeZone = c("America/Denver", 
"America/Los_Angeles", 
"America/Chicago")), class = "data.frame", row.names = c(NA, 
-3L))

我认为一个整洁的解决方案可能看起来更干净,但如果你想要一个基本的 R 解决方案,这里有一个使用@akrun 的替代方案 df1:

df1$AlertTimeLocal <- df1$AlertTimeUTC <- 
  c.POSIXct(Map(as.POSIXct, df1$AlertTime, tz = df1$TimeZone, format = "%d %b %Y, %I:%M %p"))
attr(df1$AlertTimeUTC, "tzone") <- "UTC"
attr(df1$AlertTimeLocal, "tzone") <- "US/Mountain"
df1
#               AlertTime            TimeZone        AlertTimeUTC      AlertTimeLocal
# 1 11 May 2020, 06:22 PM      America/Denver 2020-05-12 00:22:00 2020-05-11 18:22:00
# 2 11 MAY 2020, 04:11 AM America/Los_Angeles 2020-05-11 11:11:00 2020-05-11 05:11:00
# 3 10 MAY 2020, 03:38 PM     America/Chicago 2020-05-10 20:38:00 2020-05-10 14:38:00

不过,有些事情还没有讨论:在 R 中,POSIXt 的一个向量中不能有不同的时区。也就是说,在向量中,时区是 向量 的属性,而不是元素的属性。如果您在该列中的每个时间都需要单独的时区,则需要做一个列表列。这行得通,但在 data.frame.

上工作的 utilities/functions 并不总是很好地支持它