2017-01-01
不应该是PDT
,夏令时是错误的。这就是为什么如果你看看d$dates
,你会发现你的时区显然是颠倒的:R是“解决问题”(即使你不希望它)。有人可能会尝试使用format=...
参数到as.POSIXct
,但输入时不存在%
-代码,因此没有帮助。
此外,d$dates
显示时区的事实是因为R在分析时间时认真(/不小心?)假定您的本地时区。这可以通过更改日期的一个UTC显示:
d = data.frame(dates = c(as.POSIXct("2017-01-01 PDT"), as.POSIXct("2017-04-02 UTC")))
d$dates
# [1] "2017-01-01 PST" "2017-04-02 PDT"
# ^^^ is not UTC
此外,R似乎并不明白"PDT"
作为一个时区:
as.POSIXct("2017-01-01", tz = "PDT")
# ... lots of warnings ...
# [1] "2017-01-01 GMT"
但不接受类似的东西:
as.POSIXct("2017-01-01", tz = "PST8PDT")
# [1] "2017-01-01 PST"
如果你真的想要的是从原始字符串的字面部分,那么只需d$TZ <- gsub(".* ", "", d$dates)
会给你,但如果你的意图不是美容/印刷,这些可能并不全都被R识别。你可能需要翻译成“已知”的东西。
一种方法是将源更改为使用小时偏移而不是时区(例如,-0800
而不是PDT
)。这样做,你可以分析它:(我假设,因为你正在使用as.POSIXct
副想要的日期/时间标记,不只是一个日期as.Date
)
as.POSIXct("2017-01-01 -0500", format = "%Y-%m-%d %z")
# [1] "2016-12-31 21:00:00 PST"
as.POSIXct("2017-01-01 -0500", format = "%Y-%m-%d %z", tz = "UTC")
# [1] "2017-01-01 05:00:00 UTC"
另一种方法是在已知时区列表中翻译建议的时区。您可以通过?timezones
(另一个相关Q/A here)找到已知时区。
一个小测试之后(请测试这个进一步的),我想出了这个:
converttz <- function(x) {
on <- OlsonNames()
ind <- sapply(gsub(".* ", "", x), function(z) head(grep(z, on), n = 1))
ret <- character(length(x))
ret[lengths(ind) == 0] <- NA
ret[lengths(ind) > 0] <- on[unlist(ind[lengths(ind) > 0])]
ret
}
这工作只要情况下是正确的;也就是说,"est"
可能与"America/Creston"
一样容易匹配,即使您只在字符串的开头或结尾进行搜索,它仍然可以匹配"Europe/Budapest"
。
从这里,像这样的工作:
dts <- c("2017-01-01 PDT", "2017-04-02 UTC")
d <- data.frame(dates = as.POSIXct(dts), stringsAsFactors = FALSE)
d$TZ <- converttz(dts)
str(d)
# 'data.frame': 2 obs. of 2 variables:
# $ dates: POSIXct, format: "2017-01-01" "2017-04-02"
# $ TZ : chr "PST8PDT" "Etc/UTC"
好了,"Etc/UTC"
不是很悦目。 "UTC"
确实存在,但它是第二个匹配的,因此被head
过滤掉了。您可以尝试其他方法来找到更接近的匹配(可能先查找完全匹配,然后再查找开始/结束)。