17

我一直在尝试查看提取 POSIXct 列的日期组件与某个值匹配的所有行的数据框。我遇到了以下内容,这让我非常困惑::as.Date(as.POSIXct(...))并不总是返回正确的日期。

> dt <- as.POSIXct('2012-08-06 09:35:23')
[1] "2012-08-06 09:35:23 EST"
> as.Date(dt)
[1] "2012-08-05"

为什么'2012-08-06 09:35:23'的日期等于'2012-08-05 '

我怀疑这与使用的不同时区有关,所以注意到时区dt是'EST'我把它给了as.Date::

> as.Date(as.POSIXct('2012-08-06 09:35:23'), tz='EST')
[1] "2012-08-05"

但它仍然返回 2012-08-05。

为什么是这样?如何在我的数据框中找到日期为 2012-08-06 的所有日期时间?(因为即使这确实发生在日期 2012-08-06...subset(my.df, as.character(as.Date(datetime), tz='EST') == '2012-08-06')也不会返回带有 datetime 的行)?dt

添加了详细信息:Linux 64 位(虽然可以在 32 位上重现),可以在 R 3.0.1 和 3.0.0 上获得这个,我目前是 AEST(澳大利亚东部标准时间)

4

2 回答 2

18

执行此操作的安全方法是将日期值传递给format. 这确实创建了一个额外的步骤,但as.Date如果它是用“-”或“/”格式化的,则将接受字符结果:

as.Date( format( as.POSIXct('2019-03-11 23:59:59'), "%Y-%m-%d") )
[1] "2019-03-11"

as.Date(  as.POSIXct('2019-03-11 23:59:59') ) # I'm in a locale where the problem might exist
[1] "2019-03-12"

时区的文档也让我感到困惑。在某些情况下(事实证明在这种情况下),EST 可能并不明确,实际上可能指的是澳大利亚的 tz。如果您碰巧在北美,请尝试“EST5EDT”或“America/New_York”。

在这种情况下,它还可能与您未说明的操作系统如何处理“tz”参数的差异有关,因为我得到“2012-08-06”。(我目前在 PDT US tz 中,尽管我不确定这是否重要。)更改获取 tz 参数的函数可能会澄清(或不澄清):

> as.Date(as.POSIXct('2012-08-06 19:35:23', tz='EST'))
[1] "2012-08-07"
> as.Date(as.POSIXct('2012-08-06 17:35:23', tz='EST'))
[1] "2012-08-06"


> as.Date(as.POSIXct('2012-08-06 21:35:23'), tz='EST')
[1] "2012-08-06"
> as.Date(as.POSIXct('2012-08-06 22:35:23'), tz='EST')
[1] "2012-08-07"

如果您省略 tz,as.POSIXct则假定为 UTC。

这些是 Ozzie TZ 的明确名称(至少在我的 Mac 上):

tzfile <- "/usr/share/zoneinfo/zone.tab"
tzones <- read.delim(tzfile, row.names = NULL, header = FALSE,
    col.names = c("country", "coords", "name", "comments"),
    as.is = TRUE, fill = TRUE, comment.char = "#")
grep("^Aus", tzones$name, value=TRUE)
 [1] "Australia/Lord_Howe"   "Australia/Hobart"     
 [3] "Australia/Currie"      "Australia/Melbourne"  
 [5] "Australia/Sydney"      "Australia/Broken_Hill"
 [7] "Australia/Brisbane"    "Australia/Lindeman"   
 [9] "Australia/Adelaide"    "Australia/Darwin"     
[11] "Australia/Perth"       "Australia/Eucla" 
于 2013-06-13T23:42:15.250 回答
10

澳大利亚同胞在这里插话(布里斯班位置,Win7 Enterprise 64 位,R3.0.1):

我可以复制你的问题:

> dt <- as.POSIXct('2012-08-06 09:35:23')
> dt
[1] "2012-08-06 09:35:23 EST"
> as.Date(dt)
[1] "2012-08-05"

由于as.Date默认为UTC(GMT),如下所列?as.Date

## S3 method for class 'POSIXct'
as.Date(x, tz = "UTC", ...) 

然后将表示强制POSIXct为 UTC,然后按预期工作:

> dt <- as.POSIXct('2012-08-06 09:35:23',tz="UTC")
> as.Date(dt)
[1] "2012-08-06"

或者,将它们与我的本地tz作品匹配也很好:

> dt <- as.POSIXct('2012-08-06 09:35:23',tz="Australia/Brisbane")
> as.Date(dt,tz="Australia/Brisbane")
[1] "2012-08-06"

编辑:规范的歧义EST对我来说似乎是一个问题:

默认使用as.POSIXct

> dt.def <- as.POSIXct("2012-01-01 22:00:00")
> dt.def
[1] "2012-01-01 22:00:00 EST"
> as.numeric(dt.def)
[1] 1325419200
> 

模棱两可EST- 应与默认值相同

> dt.est <- as.POSIXct("2012-01-01 22:00:00",tz="EST")
> dt.est
[1] "2012-01-01 22:00:00 EST"
> as.numeric(dt.est)
[1] 1325473200
> 

明确的澳大利亚布里斯班时区

> dt.bris <- as.POSIXct("2012-01-01 22:00:00",tz="Australia/Brisbane")
> dt.bris
[1] "2012-01-01 22:00:00 EST"
> as.numeric(dt.bris )
[1] 1325419200
> 

差异

> dt.est - dt.def
Time difference of 15 hours
> dt.est - dt.bris
Time difference of 15 hours
> dt.bris - dt.def
Time difference of 0 secs
于 2013-06-14T00:29:37.953 回答