lubridate yyyy-MM-dd'T'HH:mm:ssX 转换意外。漏洞?

lubridate yyyy-MM-dd'T'HH:mm:ssX conversion unexpected. Bug?

解析 "yyyy-MM-dd'T'HH:mm:ssX"-字符串 (ISO 8601) 时出现非常意外的行为

> as_datetime("2017-03-22T15:48:00.000Z")
[1] "2017-03-21 23:00:00 UTC"

> packageDescription("lubridate")$Version 
[1] "1.6.0"

有人可以解释一下这样做的理由吗?

编辑:似乎是一个错误,参见 issue #536

更新:已在 lubridate 提交 here(2017 年 5 月)中解决。适用于 lubridate 1.7.4,可能还有一些更早的版本。

没有深入挖掘 as_datetime 的内容, 我认为这可能是 (1) as_datetime 的组合 无法处理(即忽略)格式中的 T; (2) 本地时区到UTC时区的转换。

dstr <- "2017-03-22T15:48:00.000Z"
library(lubridate)
as_datetime(dstr)
## [1] "2017-03-22 04:00:00 UTC"

如果 as_datetime() 忽略 T 之后的所有内容 这让我们到了 2017 年 3 月 22 日的午夜。然而,这是 在我的本地时区 中作为午夜 ,即 GMT+04, 所以得到的时间是 04:00:00。大概是你的当地时间 是 GMT-01。

如果您手动将 space 替换为 T,效果会更好(您可以使用 stringr::str_replace 如果你愿意的话)

as_datetime(sub("T"," ",dstr))
## [1] "2017-03-22 19:48:00 UTC"

或使用strptime:

strptime(dstr,format="%Y-%m-%dT%H:%M:%S")
## [1] "2017-03-22 15:48:00 EDT"

(注意 strptime 自动丢弃 尾随 个字符)

Dirk Eddelbuettel 的 anytime 软件包处理这种情况的价值:

 anytime(dstr)
 ## [1] "2017-03-22 15:48:00 EDT"

如果您以此处显示的格式导入数据,并且想使用 lubridate 将其转换为日期时间对象,我建议使用 lubridate 的 ymd_hms 函数。

在你的情况下它看起来像这样:

ymd_hms("2017-03-22T15:48:00.000Z")
[1] "2017-03-22 15:48:00 UTC"