R: dub 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 ответ

Решение

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"));

... как жестко закодированная строка.

Другие вопросы по тегам