检查是否在格林威治标准时间,然后在格林威治标准时间转换为当地时间 - R - 循环

check if in GMT, then convert to local time in in GMT - R - looping

我发现了一百万篇关于从格林威治标准时间转换为当地时间的帖子,但没有一个首先检查如果日期-时间是GMT,然后转换成它的代表当地时间。由于人们建议复制,我希望将 从 GMT 转换为当地时间 ,但更重要的是, 特别想检查是否需要进行转换。我正在使用 lubridatedplyrzoostringr

以这个示例数据为例(我的数据在一个更大的 nums 和 POSXIct 格式的数据框中):

对于 store 1000df 数据框具有列 Time:

Time<-c("2017-02-02 06:05:00 GMT", "2017-02-04 00:06:10 GMT", "2017-02-05 00:06:15 GMT")
df<-as.data.frame(Time)

time_zone_info如下:

x<-1000
timezone<-"US/Eastern"
time_zone_info<-cbind(x,timezone)
time_zone_info<-as.data.frame(time_zone_info)

我目前的尝试如下:

correct_to_local_time<-function(df){     
    if("GMT" %in% df$Time){
        df$Time<-as.POSIXct(df$Time, tz ="GMT",usetz=TRUE) 
        df$Time<-with_tz(df$Time,tz=time_zone_info$timezone)
        }
    else{
           as.POSIXct(df$Time)}
}
correct_to_local_time(df)

这给了我以下计算不正确的(它应该是 1:05:00EDT、01:10:00EDT 等,但它确实将 GMT 更改为 EDT,所以我很困惑.. .):

Time
2017-02-02 06:05:00 EDT
2017-02-02 06:10:00 EDT
2017-02-02 06:10:00 EDT

理想情况下,我想要这样的东西:

 Local Time        
2017-02-02 01:05:00 EDT
2017-02-04 01:10:00 EDT
2017-02-05 01:15:00 EDT

从 GMT 转换为 EDT 或 MST 后,夏令时是否考虑在内?

提前谢谢大家

软件包 lubridate 可能可以帮助您。

 require(lubridate)

dfTime<-c("2017-02-02 06:05:00 GMT", 
          "2017-02-04 00:06:00 New_York",
          "2017-02-05 00:06:00 US/Mountain")
dfStore <-c(1000, 2000, 3000)
dftimeZone<-c("US/Eastern", "US/Eastern", "US/Mountain")

time_zone_info <- data.frame(Store = dfStore,
                             Time = dfTime,
                             Timezone = dftimeZone,
                             stringsAsFactors = FALSE)

首先,检查您的所有时区是否都在系统识别的时区列表内。 (我不确定。)

all(time_zone_info$Timezone %in% OlsonNames())

好的,很好。

接下来,将你的时间字符串转换成POSIXct。我喜欢这里的 lubridate 函数 "ymd_hms",因为它非常灵活。您也可以使用参数 "tz" 设置时区。这 returns 时间 在您当前的时区 。例如,我在西雅图,所以这个 returns 对我来说是太平洋标准时间的等效时间。我很确定 lubridate 会考虑夏令时。 (我很难让它适用,因此选择了 "for" 循环。不过,我相信其他人可以在没有它的情况下做到这一点。)

time_zone_info$Time2 <- as.POSIXct(NA)
for(i in 1:nrow(time_zone_info)){
      time_zone_info$Time2[i] <- ymd_hms(time_zone_info$Time[i], 
                                         tz = time_zone_info$Timezone[i])
}

time_zone_info$Time2 中的所有内容都将处于同一时区,我相信这是为了方便比较而设计的。很难让R在data.frame的同一列中制作多个时区。

让我们首先制作一个 data.frame ,它更接近您实际使用的内容,并且比您提交一行的单列 data.frame 更容易使用到你的功能。

df <- data.frame(
      Store = c(1000, 2000, 3000),
      Time = c("2017-02-02 06:05:00 GMT",
               "2017-02-04 00:06:10 GMT",
               "2017-02-05 00:06:15 GMT"),
      stringsAsFactors = FALSE)

同样,让我们​​更简洁地编写另一个 data.frame 并制作 类 字符串而不是因子,因为因子会使您出错。 (这与其说是要求,不如说是偏好。)

time_zone_info <- data.frame(
      Store = 1000,
      timezone = "US/Eastern",
      stringsAsFactors = FALSE)

您的函数存在一个问题,即您使用错误的语法来检查字符 "GMT" 是否在您的字符串中。你不想要 %in%;你想要 stringr 方便的 str_detect 功能。

此外,与其输入一个 data.frame 并输出一个 data.frame,这在您当前应用它时可能会很棘手,让我们设计函数以便输入是单个字符串并且输出是单个字符串,更易于使用。

require(stringr)
require(lubridate)

correct_to_local_time<-function(InputTime){     
      if(str_detect(InputTime, "GMT")){
            GMTTime <- as.POSIXct(InputTime, tz = "GMT", usetz = TRUE) 
            OutputTime <- with_tz(GMTTime, tz = time_zone_info$timezone)
      } else {
            OutputTime <- as.POSIXct(InputTime)}

      return(OutputTime)
}
correct_to_local_time(df$Time[1])

如果我是你,我也会严格检查你函数的 else 部分是否返回你想要的;我可以看到不使用非标准化时区信息。