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

Posted

技术标签:

【中文标题】R:lubridate 的 dst() 没有按预期工作【英文标题】:R: lubridate's dst() not working as expected 【发布时间】:2017-06-15 04:26:18 【问题描述】:

我怀疑我在做一些非常愚蠢的事情,但我无法让lubridate 中的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)。

【问题讨论】:

嗨 pbaylis,您能告诉我们您期望的结果吗? dst(x) 为我返回 c(FALSE,FALSE)。你在哪个时区? dst(x) 调用使用系统时区的as.POSIXlt(x)$isdst 我期待 c(FALSE, TRUE) 并且我在 PST(相应地编辑了问题)。 不幸的是,Mac 的系统时区有时是 "",但我无法在运行 R 3.3.2 RC 的 ElCap 机器上重现。我得到[1] FALSE TRUE 我可以使用 c(NA, FALSE, TRUE)[as.POSIXlt(x,tz="America/Los_Angeles")$isdst + 2]c(NA, FALSE, TRUE)[as.POSIXlt(as.Date(x),tz="America/Los_Angeles")$isdst + 2] 进行复制 - 根据 dst.default 中的代码 【参考方案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"));

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

【讨论】:

谢谢,这很有启发性。这对我来说似乎是一个错误,但我不确定。 as.POSIXlt 的 documentation 表示“没有时间的日期被视为 UTC 午夜”,所以这可能是预期的行为。我现在的解决方法是使用as.character(as.Date(x)),但我有一个大数据集,转换为字符向量的成本很高。

以上是关于R:lubridate 的 dst() 没有按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

R:Lubridate 无法将字符转换为数字

R Lubridate dmy 输出格式

r 将字符串转换为datetime lubridate

R语言使用lubridate包的tz函数设置和查询日期时间对象的时区信息( time zone)

为啥 R lubridate::duration 数据类型使用 sparklyr 转换为 spark 中的字符?

R语言将数据列中的多种日期格式统一变化为一种固定格式实战:使用lubridate包中的parse_date_time函数