I suspect I am doing something very silly, but I can't get the dst
function in lubridate
to work as expected.
library(lubridate)
x <- c("2016-01-01", "2016-06-01")
dst(x) # Returns c(FALSE, TRUE)
dst(as.Date(x)) # Returns c(FALSE, FALSE)
The result I expect in both cases is c(FALSE, TRUE)
. However, I only get the expected result if I pass dst
a character vector and not with a Date
object. I'm using OS X, my current timezone is PST (America/Los_Angeles
).
dst()
calls a piece of code which is essentially:
c(NA, FALSE, TRUE)[as.POSIXlt(x)$isdst + 2]
as.POSIXlt
is by default:
as.POSIXlt(x=, tz="")
...which will take your system timezone by default. So, given your location in L.A., let's look at:
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
Everything is fine. Hooray. Now, let's try with 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"
Ohhh. So, as.POSIXlt
does not play nicely with Date
objects, and always returns UTC
instead of the local timezone, and seemingly ignores any tz=
argument. And since UTC
does not abide by any daylight savings, you will always end up with FALSE
returned.
Looking at the R source code, this seems to be the case. In https://svn.r-project.org/R/trunk/src/main/datetime.c you can find:
# 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"));
...as a hard-coded string.