R:lubridate's dst()不按预期方式工作

问题描述:

我怀疑我做的事情非常愚蠢,但我无法使dst函数在lubridate中按预期工作。R:lubridate's dst()不按预期方式工作

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)。

+2

嗨pbaylis,你能告诉我们你期望的结果吗? –

+1

'dst(x)'为我返回'c(FALSE,FALSE)'。你在什么时区? 'dst(x)'调用as.POSIXlt(x)$ isdst',它使用系统时区。 – thelatemail

+0

我期望'c(FALSE,TRUE)'和我在PST(相应编辑的问题)。 – pbaylis

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.POSIXltDate对象不搭配很好,并且始终返回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")); 

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

+0

谢谢,这是很有启发性的。这对我来说似乎是一个错误,但我不确定。 'as.POSIXlt'的[documentation](https://stat.ethz.ch/R-manual/R-devel/library/base/html/as.POSIXlt.html)表示“没有时间的日期被视为存在在UTC的午夜,“或许这是预期的行为。 我现在的解决方法是使用'as.character(as.Date(x))',但是我有一个大的数据集,并且转换为字符向量的代价很高。 – pbaylis