R:lubridate的dst()没有按预期工作

时间:2017-01-30 03:40:20

标签: r timezone dst lubridate

我怀疑我做的事情非常愚蠢,但我无法让dst中的lubridate函数按预期工作。

library(lubridate)

x <- c("2016-01-01", "2016-06-01")

dst(x) # Returns c(FALSE, TRUE)
dst(as.Date(x)) # Returns c(FALSE, FALSE)

我在两种情况下的结果都是c(FALSE, TRUE)。但是,如果我传递dst一个字符向量而不是一个Date对象,我只会得到预期的结果。我使用的是OS X,我目前的时区是PST(America/Los_Angeles)。

1 个答案:

答案 0 :(得分:3)

dst()调用一段代码,基本上是:

c(NA, FALSE, TRUE)[as.POSIXlt(x)$isdst + 2]
默认情况下

as.POSIXlt

as.POSIXlt(x=, tz="")

...默认情况下会占用您的系统时区。所以,鉴于你在洛杉矶的位置,让我们来看看:

as.POSIXlt(x, tz="America/Los_Angeles")
#[1] "2016-01-01 PST" "2016-06-01 PDT"
c(NA, FALSE, TRUE)[as.POSIXlt(x, tz="America/Los_Angeles")$isdst + 2]
#[1] FALSE  TRUE

一切都很好。万岁。现在,让我们试试as.Date(x)

as.POSIXlt(as.Date(x))
#[1] "2016-01-01 UTC" "2016-06-01 UTC"
as.POSIXlt(as.Date(x), tz="America/Los_Angeles")
#[1] "2016-01-01 UTC" "2016-06-01 UTC"

哦~~。因此,as.POSIXlt不能很好地与Date个对象一起使用,并且始终返回UTC而不是本地时区,并且似乎忽略了任何tz=参数。由于UTC不遵守任何夏令时,因此您最终会返回FALSE

看看R源代码,似乎就是这种情况。在https://svn.r-project.org/R/trunk/src/main/datetime.c中,您可以找到:

# R call:
#> as.POSIXlt.Date
#function (x, ...) 
#.Internal(Date2POSIXlt(x))

# source code:
#SEXP attribute_hidden do_D2POSIXlt(SEXP call, SEXP op, SEXP args, SEXP env)
#{
#...
setAttrib(ans, s_tzone, mkString("UTC"));

...作为硬编码字符串。