2017-01-30 115 views
1

我懷疑我做的事情非常愚蠢,但我無法使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

回答

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.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