【问题标题】:Using strptime %z with special timezone format使用带有特殊时区格式的 strptime %z
【发布时间】:2013-02-22 19:53:05
【问题描述】:

我正在处理从 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"

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

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

【问题讨论】:

    标签: r timezone strptime string-to-datetime


    【解决方案1】:

    原来lubridate可以处理这种格式:

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

    或者,以当地时区显示:

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

    为了获得更大的灵活性(仍然使用lubridate):

    parse_date_time(x, "%Y-%m-%d %H:%M:%OS%z")
    

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

    lubridate:::.strptime(x, "%Y-%m-%d %H:%M:%OS%OO")
    

    时间安排:

    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
    

    【讨论】:

      【解决方案2】:

      我刚刚遇到这个问题,试图实现同样的目标。

      正如您所提到的,我发现修复它的唯一方法是使用正则表达式删除冒号。您可以稍微收紧正则表达式以避免在替换时出错。

      x2 <- gsub('^([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]+[+-][0-9]{2}):([0-9]{2})$',
                 '\\1\\2',
                 x)
      # [1] "2011-10-12 22:17:13.860746-0400" "2011-10-12 22:17:13.860746+0000"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-16
        • 1970-01-01
        • 2020-02-20
        • 2019-09-02
        • 1970-01-01
        • 1970-01-01
        • 2015-08-15
        • 1970-01-01
        相关资源
        最近更新 更多