R将日期,时间和时区字符串转换为POSIXct

时间:2018-04-13 21:11:53

标签: r timezone posixct

日期解析错误

我在角色日期转换方面遇到问题,并希望能帮助您了解出现问题的原因。为此,我定义了一个包含两行的非常简单的数据框,其中包含每行的ID,时区,日期和时间。我想添加一个包含(例如)POSIXct条目的列,用于组合日期时间,包括正确的时区。 (这是一个合成示例,但我想将其应用于更大的数据集。)

首先,我们尝试使用R的基础设施将这些功能组合成数据,时间和时区的统一表示。

d <- data.frame(id=c(111, 222), 
            tzz=c("Europe/Berlin", "US/Eastern"), 
            d=c("09-Sep-2017", "11-Sep-2017"), 
            t=c("23:42:13", "22:05:17"),
            stringsAsFactors = FALSE)

d$dt <- strptime(paste(d$d, d$t), tz=d$tzz, format="%d-%b-%Y %T")

Error in strptime(paste(d$d, d$t), tz = d$tzz, format = "%d-%b-%Y %T") : 
  invalid 'tz' value

这种方法失败了,虽然我不明白为什么。例如,我可以轻松地完成此非矢量化版本。此外,我使用的时区似乎是官方支持列表的一部分。

d$tzz %in% OlsonNames()

[1] TRUE TRUE

dt1 <- strptime(paste(d$d[1], d$t[1]), tz=d$tzz[1], format="%d-%b-%Y %T")
print(dt1)
[1] "2017-09-09 23:42:13 CEST"

print(tz(dt1))
[1] "Europe/Berlin"

dt2 <- strptime(paste(d$d[2], d$t[2]), tz=d$tzz[2], format="%d-%b-%Y %T")

print(dt2)
[1] "2017-09-11 22:05:17 EDT"

print(tz(dt2))
[1] "US/Eastern"

另外,考虑到我的问题可能是误解了如何使用strptime,然后我尝试了类似的方法与lubridate:

library(lubridate)
d$dt <- dmy_hms(paste(d$d, d$t), tz=d$tzz)

Error in strptime(.enclose(x), .enclose(fmt), tz) : invalid 'tz' value

但得到了同样的错误。同样,非矢量版本工作正常。

dt1l <- dmy_hms(paste(d$d[1], d$t[1]), tz=d$tzz[1])
print(dt1l)
[1] "2017-09-09 23:42:13 CEST"

print(tz(dt1l))
[1] "Europe/Berlin"

在tidyverse中尝试mutate会产生同样的问题。 (顺便说一句,CEST不属于OlsonNames集。)

非常感谢有关如何正确执行此操作的帮助,或者至少解释了这是如何出错的。

2 个答案:

答案 0 :(得分:1)

尝试逐行计算:

library(dplyr)
d %>%
  rowwise() %>%
  mutate(ct = as.POSIXct(paste(d, t), format = "%d-%b-%Y %H:%M:%S", tz = tzz)) %>%
  ungroup

,并提供:

# A tibble: 2 x 5
     id tzz           d           t        ct                 
  <dbl> <chr>         <chr>       <chr>    <dttm>             
1  111. Europe/Berlin 09-Sep-2017 23:42:13 2017-09-09 17:42:13
2  222. US/Eastern    11-Sep-2017 22:05:17 2017-09-11 22:05:17

答案 1 :(得分:0)

类似于Gabor,但data.table使用的是id是唯一的:

R> dt <- data.table(d)
R> dt[ , ct := as.POSIXct(paste(d, t), "%d-%b-%Y %H:%M:%S", tz=tzz), by=id][]
    id           tzz           d        t                  ct
1: 111 Europe/Berlin 09-Sep-2017 23:42:13 2017-09-09 17:42:13
2: 222    US/Eastern 11-Sep-2017 22:05:17 2017-09-11 22:05:17
R>