【问题标题】:Reading timestamp data in R from multiple time zones从多个时区读取 R 中的时间戳数据
【发布时间】:2015-12-28 21:12:39
【问题描述】:

我有一列字符格式的时间戳,如下所示:

2015-09-24 06:00:00 UTC

2015-09-24 05:00:00 UTC

dateTimeZone <- c("2015-09-24 06:00:00 UTC","2015-09-24 05:00:00 UTC")

我想使用 POSIXct 将此字符数据转换为时间数据,如果我知道所有时间戳都是 UTC,我会这样做:

dateTimeZone <- asPOSIXct(dateTimeZone, tz="UTC")

但是,我不一定知道所有时间戳都是 UTC,所以我尝试了

dateTimeZone <- asPOSIXct(dateTimeZodateTimeZone, format = "%Y-%m-%d %H:%M:%S %Z")

但是,由于 strptime 仅支持 %Z 用于输出,因此返回以下错误:

strptime(x, format, tz = tz) 中的错误: 不支持使用 %Z 进行输入

我检查了 lubridate 包的文档,我看不出它处理这个问题的方式与 POSIXct 有什么不同。

我唯一的选择是检查每一行的时区,然后使用适当的时区,如下所示?

temp[grepl("UTC",datetimezone)] <- as.POSIXct(datetimezone, tz="UTC")
temp[grepl("PDT",datetimezone)] <- as.POSIXct(datetimezone, tz="America/Los_Angeles")

【问题讨论】:

    标签: r datetime timezone


    【解决方案1】:

    您可以通过检查每一行并进行相应处理,然后将所有内容放回一致的 UTC 时间来到达那里。 (#edited 现在包括将时区缩写与完整时区规范匹配)

    dates <- c(
      "2015-09-24 06:00:00 UTC",
      "2015-09-24 05:00:00 PDT"
    )
    
    #extract timezone from dates
    datestz <- vapply(strsplit(dates," "), tail, 1, FUN.VALUE="")
    
    ## Make a master list of abbreviation to 
    ## full timezone names. Used an arbitrary summer
    ## and winter date to try to catch daylight savings timezones.
    
    tzabbrev <- vapply(
      OlsonNames(),
      function(x) c(
        format(as.POSIXct("2000-01-01",tz=x),"%Z"),
        format(as.POSIXct("2000-07-01",tz=x),"%Z")
      ),
      FUN.VALUE=character(2)
    )
    tmp <- data.frame(Olson=OlsonNames(), t(tzabbrev), stringsAsFactors=FALSE)
    final <- unique(data.frame(tmp[1], abbrev=unlist(tmp[-1])))
    
    ## Do the matching:
    out <- Map(as.POSIXct, dates, tz=final$Olson[match(datestz,final$abbrev)])
    as.POSIXct(unlist(out), origin="1970-01-01", tz="UTC")
    #  2015-09-24 06:00:00 UTC   2015-09-24 05:00:00 PDT 
    #"2015-09-24 06:00:00 GMT" "2015-09-24 12:00:00 GMT" 
    

    【讨论】:

      【解决方案2】:

      data.table 解决方案:

      library(data.table)
      
      data <- data.table(dateTimeZone=c("2015-09-24 06:00:00 UTC",
                                        "2015-09-24 05:00:00 America/Los_Angeles"))
      data[, timezone:=tstrsplit(dateTimeZone, split=" ")[[3]]]
      data[, datetime.local:=as.POSIXct(dateTimeZone, tz=timezone), by=timezone]
      data[, datetime.utc:=format(datetime.local, tz="UTC")]
      

      关键是拆分时区字段上的数据,以便您可以将每组时区分别提供给as.POSIXct(我不太确定为什么as.POSIXct 不允许您给它一个向量时区,实际上)。在这里,我使用了data.table 的高效拆分-应用-组合语法,但您可以使用基本 R 或 dplyr 应用相同的一般概念。

      【讨论】:

      • 优雅的答案。我喜欢 data.table - 我以前从未遇到过tstrsplit。仅此一项就值得!
      【解决方案3】:

      使用lubridate的另一种方式...

      library(stringr)
      library(lubridate)
      
      normalize.timezone <- function(dates, target_tz = local.timezone) {
          tzones <- str_split(dates, ' ')
          tzones <- lapply(tzones, '[', 3)
          tzones <- unlist(tzones)
          dts <- str_replace_all(dates, ' [\\w\\-\\/\\+]+$', '')
          tmp <- lapply(1:length(dates), function(i) {
              with_tz(as.POSIXct(dts[ i ], tz = tzones[ i ]), target_tz)
          })
          final <- unlist(tmp)
          attributes(final) <- attributes(tmp[[ 1 ]])
          final
      }
      
      dates <- c('2019-01-06 23:00:00 MST', 
                 '2019-01-22 14:00:00 America/Los_Angeles', 
                 '2019-01-05 UTC-4', 
                 '2019-01-15 15:00:00 Europe/Moscow')
      (normalize.timezone(dates, 'EST'))
      

      【讨论】:

        猜你喜欢
        • 2015-08-27
        • 1970-01-01
        • 2020-09-22
        • 1970-01-01
        • 2014-04-26
        • 1970-01-01
        • 2012-07-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多