【问题标题】:as.Date(as.POSIXct()) gives the wrong date?as.Date(as.POSIXct()) 给出错误的日期?
【发布时间】:2013-06-10 12:50:04
【问题描述】:

我一直在尝试查看一个数据框,提取 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 的所有日期时间? (因为subset(my.df, as.character(as.Date(datetime), tz='EST') == '2012-08-06') 不会返回日期时间为dt 的行,即使这确实发生在日期 2012-08-06...)?

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

【问题讨论】:

  • 在这里按预期工作(时区 CEST 中的 R 3.0.0)
  • @profPlum,非常无益的评论。我不能或不会使用 Python 的原因有很多——例如工作要求,在更大的软件套件中工作,需要做大量的统计分析/绘图,R 可以更好地支持开箱即用,或者只是流利地使用 R 而不是 Python!
  • @mathematical.coffee 抱歉,我正处于了解 R 的幻灭阶段。我只是看到语言基础上有很多漏洞,但我承认这只是一种观点。

标签: r datetime timezone


【解决方案1】:

执行此操作的安全方法是通过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"

如果您省略 as.POSIXct 中的 tz,则假定为 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" 

【讨论】:

  • 我目前在澳大利亚东部标准时间。我假设as.POSIXct 的默认tz 是“EST”,因为当我执行as.POSIXct(...) 时,我得到一个附加了“EST”的字符串(查看我定义dt 时打印的内容)。 Linux,R 3.0.1。我会试着把 tz 放在不同的地方。
  • as.Date(dt, tz='EST') 为我返回“2012-08-05”,但 as.Date(dt, tz='Australia/Brisbane') 返回“2012-08-06”。我想正如你提到的“EST”是模棱两可的(如果 R 告诉我这样的话会很好......)
  • 啊哈。我会大胆猜测,更多的人会做出相反的假设,即“EST”是美国东部 TZ。也许您可以发布维基百科至少认为不那么模棱两可的“AEST”结果:en.wikipedia.org/wiki/Time_in_Australia 尽管即使在您的“EST”内沿 NS 轴也有变化。
  • AEST 给我unknown timezone 'AEST' - 我在下面添加了位置和操作系统信息。
【解决方案2】:

澳大利亚同胞在这里插话(布里斯班位置,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

【讨论】:

  • as.Date(dt, tz='EST') 为我返回“2012-08-05”,但as.Date(dt, tz='Australia/Brisbane') 返回“2012-08-06”。我想@DWin 提到“EST”是模棱两可的(如果 R 告诉我这样的话会很好......)
  • 你们都没有提到你的操作系统,它是 TZ 数据库的存储库。我正在发布我的答案的附录。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-12
  • 2012-11-23
  • 2017-03-25
  • 1970-01-01
相关资源
最近更新 更多