如何在R中将整个日期/时间列从一个时区转换为另一个时区?

时间:2018-03-05 07:35:36

标签: r timezone posixct posixlt

enter image description here

每一行都有不同的origintimezone。我需要使用原始时区时间的standardformat_new列来创建一个新列,其中时间跟在com_timezonenames之后。

简化版本就是这样的

a = ymd_hms('2017-10-10 10:20:00',tz = 'Australia/Sydney')
a
with_tz(a, tz = 'Singapore')

[![在此处输入图像说明] [2]] [2]

但是,当我在上面使用类似的代码时,我遇到以下错误。

[![在此处输入图像说明] [3]] [3]

我试过制作一个for循环来运行整个列表,但是数十万的数据集使它变得不可行。

REPREX as reqeusted 这就是我最初的想法。

[![在此输入图像说明] [4]] [4]

structure(list(com_country = c("SG", "AU", "NZ", "UK", "AU", 
"AU"), orderdate_local = c("9/20/2017 4:47:35 AM", "9/30/2017 7:00:00 AM", 
"9/20/2017 1:37:14 AM", "9/18/2017 9:38:34 PM", "9/30/2017 3:07:29 AM", 
"9/30/2017 10:17:01 AM"), origincountry = c("US", "AU", "UK", 
"AU", "AU", "AU")), .Names = c("com_country", "orderdate_local", 
"origincountry"), row.names = c(NA, -6L), class = c("tbl_df", 
"tbl", "data.frame"))

orderdate_local在origincountry时区给出,所以我需要将国家代码映射到tz值。

##getting origin timezone from countrycode
dd$origintimezone <- mapvalues(dd$origincountry, 
                                      from=c("AU", "UK", "US"), 
to=c("Australia/Sydney","Europe/London","America/Toronto"))

此后我需要将orderdate_local转换为标准POSIXlt格式,以便我可以使用strptime函数

dd$standardformat_new <- strptime(dd$orderdate_local,format="%m/%d/%Y 
%I:%M:%S %p")
dd$com_timezonenames <- mapvalues(dd$com_country, 
                      from=c("AU","MY","NZ","SG","PH","HK","UK","TH"), 
                              to=c("Australia/Sydney", "Asia/Kuala_Lumpur", "Pacific/Auckland","Asia/Singapore","Asia/Manila","Asia/Hong_Kong","Europe/London","Asia/Bangkok"))

这就是我们现在所拥有的。 enter image description here

3 个答案:

答案 0 :(得分:1)

在尝试使用您的reprex的几个选项并且在尝试强制它接受日期时间向量的不同元素的不同时区时遇到无效的'tz'值时编辑,我挖掘了文档以找到这个:

  

R日期时间向量无法保存具有非均匀时区的元素

看起来您必须以UTC时间存储日期时间,这实在令人沮丧。

这是你如何做到的:

dd$standardformat_new <- force_tzs(mdy_hms(dd$orderdate_local), 
                                   tzones = dd$com_timezonenames)

上面的代码使用lubridate包将表示日期和时间的非标准字符向量转换为日期时间对象,将生成的Olson Name时区作为输入,并生成对应于的UTC时间向量指定时区的当地时间。遗憾的是,这不是很好和可读,但它确实具有准确表示时区之间的相对时间的优点,并允许您作为日期时间对象对矢量执行进一步计算。当然,您可以选择使用不同的时区显示数据(只需将tzone_out设置为其他时区),但它必须是所有值的相同时区。

感谢你把reprex放在一起。我希望这有点帮助

答案 1 :(得分:0)

        ##getting origin timezone from countrycode
        dd$origintimezone <- mapvalues(dd$origincountry, 
                               from=c("AU", "UK", "US"), 

        to=c("Australia/Sydney","Europe/London","America/Toronto"))

        ##getting com_country timezone 
        dd$com_timezonenames <- mapvalues(dd$com_country, 

        from=c("AU","MY","NZ","SG","PH","HK","UK","TH"), 
                                  to=c("Australia/Sydney", 
        "Asia/Kuala_Lumpur","Pacific/Auckland","Asia/Singapore","Asia/Manila","Asia/Hong_Kong","Europe/London","Asia/Bangkok"))




         dd$origintimezoneTIME <- force_tzs(mdy_hms(dd$orderdate_local),tzones = 
         dd$origintimezone,tzone_out = "UTC")
         dd_table <- data.table(A = 1:nrow(dd),
                       origintimezoneTIME_UTC = dd$origintimezoneTIME,
                       com_timezonenames = dd$com_timezonenames,
                       com_country = dd$com_country,
                       orderdate_local = dd$orderdate_local,
                       origincountry = dd$origincountry,
                       origintimezone = dd$origintimezone)

       dd_table[ , com_countryTIME := format(toTz(origintimezoneTIME_UTC, "UTC", 
       com_timezonenames), tz=com_timezonenames), by=A ]

在此页面的帮助下编写代码Adjusting UTC date/time to different time zones by reference in lubridate

答案 2 :(得分:0)

dl%>%
  mutate(time1 = as.POSIXct(strptime(orderdate_local,format="%m/%d/%Y %I:%M:%S %p",tz="GMT")),
         time2 = ymd_hms(unlist(lapply(seq(length(time1)),
                                       function(x) {format(with_tz(force_tz(time1[x], com_timezonenames[x]),"GMT"), "%F %T")}))),
         time3 = ymd_hms(unlist(lapply(seq(length(time2)), 
                                       function(x) {format(with_tz(time2[x], origintimezone[x]), "%F %T")}))))

另一个更简单的解决方案,没有任何花哨的库