使用特殊时区格式的strptime%z

dnl*_*rky 8 timezone r strptime string-to-datetime

我正在使用从Teradata导出的.csv数据.有几列原本是带时区的时间戳,所以在加载R中的.csv之后,我想将这些列(作为字符串加载)转换为POSIXlt或POSIXct.我正在使用strptime,但.csv文件中的时区格式与strptime预期的不匹配.例如,它希望-0400但.csv具有-04:00冒号分隔小时和分钟的格式.

我可以删除结肠,但这是一个额外的步骤和复杂性我想尽可能避免.有没有办法让strptime时区(%z)使用不同的格式?

这是一个例子:

## Example data:
x <- c("2011-10-12 22:17:13.860746-04:00", "2011-10-12 22:17:13.860746+00:00")
format <- "%Y-%m-%d %H:%M:%OS%z"

## Doesn't work:
strptime(x,format)
## [1] NA NA

## Ignores the timezone:
as.POSIXct(x)
## [1] "2011-10-12 22:17:13 EDT" "2011-10-12 22:17:13 EDT"

## Remove the last colon:
x2 <- gsub("(.*):", "\\1", x)
x2
## [1] "2011-10-12 22:17:13.860746-0400" "2011-10-12 22:17:13.860746+0000"

## This works, but requires extra processing (removing the colon)
strptime(x2,format)
## [1] "2011-10-12 22:17:13" "2011-10-12 18:17:13"
Run Code Online (Sandbox Code Playgroud)

所以我希望使用类似的东西来实现最后的结果strptime(x,"%Y-%m-%d %H:%M:%OS%zz"),其中%zz是用于识别-04:00格式的时区的自定义表达式.或者%zH:%zM可能更好.

如果这是不可能的,有没有人有一个光滑/灵活的功能,用于将字符串(各种格式)转换为data.frame/data.table的多列的日期?

dnl*_*rky 6

事实证明lubridate可以处理这种格式:

library(lubridate)
ymd_hms(x)
## [1] "2011-10-13 02:17:13 UTC" "2011-10-12 22:17:13 UTC"
Run Code Online (Sandbox Code Playgroud)

或者,在本地时区显示:

with_tz(ymd_hms(x))
## [1] "2011-10-12 22:17:13 EDT" "2011-10-12 18:17:13 EDT"
Run Code Online (Sandbox Code Playgroud)

为了更灵活(仍在使用lubridate):

parse_date_time(x, "%Y-%m-%d %H:%M:%OS%z")
Run Code Online (Sandbox Code Playgroud)

为了更快的速度(在lubridate选项中):

lubridate:::.strptime(x, "%Y-%m-%d %H:%M:%OS%OO")
Run Code Online (Sandbox Code Playgroud)

时序:

microbenchmark(
  ymd_hms(x),
  parse_date_time(x, "%Y-%m-%d %H:%M:%OS%z"),
  lubridate:::.strptime(x, "%Y-%m-%d %H:%M:%OS%OO"),
  strptime(gsub("(.*):", "\\1", x), format)
)

## Unit: microseconds
##                                               expr      min       lq       mean    median        uq      max neval
##                                         ymd_hms(x) 1523.819 1578.495 1715.14577 1629.5385 1744.3695 2850.393   100
##         parse_date_time(x, "%Y-%m-%d %H:%M:%OS%z") 1108.676 1150.633 1273.77301 1190.3315 1264.8050 5947.204   100
##  lubridate:::.strptime(x, "%Y-%m-%d %H:%M:%OS%OO")   89.838  103.390  112.45338  107.8425  115.2265  216.512   100
##        strptime(gsub("(.*):", "\\\\1", x), format)   46.716   58.294   71.90934   69.9415   86.5860  105.044   100
Run Code Online (Sandbox Code Playgroud)