【问题标题】:How to extract the correct timezones from POSIXct and POSIXlt objects?如何从 POSIXct 和 POSIXlt 对象中提取正确的时区?
【发布时间】:2011-05-20 11:17:28
【问题描述】:
time1 = as.POSIXlt("2010-07-01 16:00:00", tz="Europe/London")
time1
# [1] "2010-07-01 16:00:00 Europe/London"

但是

time2 = as.POSIXct("2010-07-01 16:00:00", tz="Europe/London")
time2
# [1] "2010-07-01 16:00:00 BST"

为什么时区的显示方式不同?这对我很重要,因为我需要从我的日期中提取时区。

base::format(time1, format="%Z")
# [1] "BST"
base::format(time2, format="%Z")
# [1] "BST"

两者都为英国节省时间提供相同的“BST”!

问题是“BST”无法被 POSIXct/POSIXlt 格式识别:

as.POSIXlt("2010-07-01 16:00:00", tz="BST")
# [1] "2010-07-01 16:00:00 BST"
# Warning messages:
# 1: In strptime(xx, f <- "%Y-%m-%d %H:%M:%OS", tz = tz) :
#   unknown timezone 'BST'
# 2: In structure(xx, class = c("POSIXct", "POSIXt"), tzone = tz) :
#   unknown timezone 'BST'
# 3: In strptime(x, f, tz = tz) : unknown timezone 'BST'
as.POSIXct("2010-07-01 16:00:00", tz="BST")
# [1] "2010-07-01 16:00:00 GMT"
# Warning messages:
# 1: In strptime(xx, f <- "%Y-%m-%d %H:%M:%OS", tz = tz) :
#   unknown timezone 'BST'
# 2: In structure(xx, class = c("POSIXct", "POSIXt"), tzone = tz) :
#   unknown timezone 'BST'
# 3: In strptime(x, f, tz = tz) : unknown timezone 'BST'
# 4: In structure(xx, class = c("POSIXct", "POSIXt"), tzone = tz) :
#   unknown timezone 'BST'
# 5: In as.POSIXlt.POSIXct(x, tz) : unknown timezone 'BST'

我真的很困惑。 我有两个问题:

1/POSIXct和POSIXlt格式有什么区别

2/ 有人知道我可以使用哪个时区吗?

"Europe/London" 适用于 POSIXlt 但不适用于 POSIXct。此外,无法使用 base::format 从时间中提取它
"BST"as.POSIXctas.POSIXlt 函数中未被识别为有效时区。

【问题讨论】:

  • 这两个结果是来自两个不同的操作系统还是版本?
  • @Dirk Eddelbuettel:同一台计算机,相同版本的 R&packages。我在 Windows XP 上。 POSIXct 评估时区,根据季节将欧洲/伦敦替换为 GMT 或 BST
  • 我设法用一个技巧从 time1 中提取了“欧洲/伦敦” base::format(time1, format=" ", usetz = TRUE) 但它没用它表明,一旦我将这个 POSIXlt 放入 xts 中,它就会转换回 POSIXct,然后我松开“欧洲/伦敦”
  • 认为警告是 Windows 问题...as.POSIXlt("2010-07-01 16:00:00", tz="BST") 在 OS X 上运行良好
  • @tim_yates:感谢您提供的信息

标签: r timezone posix


【解决方案1】:

@Koshke 已经向你展示了

  • 两种日期类型的内部表示形式的差异,以及
  • 在内部,两个时区规范是相同的。

您可以使用attr() 以标准化方式获取时区。这将以zone.tab 文件中指定的形式获取时区,R 使用该文件来定义时区(更多信息在?timezones 中)。

例如:

> attr(time1,"tzone")
[1] "Europe/London"
> attr(time2,"tzone")
[1] "Europe/London"

虽然 POSIXct 使用与 POSIXlt 不同的时区指示,但属性是相同的,但我感到非常惊讶。显然,这个“BST”只有在打印 POSIXct 时才会弹出。在打印之前,POSIXct 被再次转换为 POSIXlt,并且 tzone 属性被修改为同义词:

> attr(as.POSIXlt(time2),"tzone")
[1] "Europe/london" "GMT"           "BST"   

这发生在 internal R 函数as.POSIXlt 的下游某处,由于要解决更严重的问题,我目前无法查看。但是请随意浏览它,看看那里到底发生了什么。

在旁注中,“BST”在我的 Windows 7 / R 2.13.0 安装中未被识别为时区(zone.tab 中也未提及)。

【讨论】:

  • 我同意,“欧洲/伦敦”更加明确,应该被首选。谢谢你的回答,很有帮助
【解决方案2】:

也许,unclass对象可以帮助您检查差异:

> unclass(time1)
$sec
[1] 0

$min
[1] 0

... snip

$yday
[1] 181

$isdst
[1] 1

attr(,"tzone")
[1] "Europe/London"

> unclass(time2)
[1] 1277996400
attr(,"tzone")
[1] "Europe/London"

因此,POSIXlt 包含日期作为组件列表,而 POSIXct 包含日期作为数字,即 UNIX 纪元时间。

至于时区,超出了R的范围。
http://en.wikipedia.org/wiki/Tz_database中的解释

至于不同的行为

as.POSIXct("2010-07-01 16:00:00", tz="BST")
as.POSIXlt("2010-07-01 16:00:00", tz="BST")

我怀疑 as.POSIXct 中存在错误,它不处理 tz 参数。

【讨论】:

  • 参见 ?DateTimeClasses -- POSIXctPOSIXlt 的处理方式略有不同,而且,说得委婉些,很复杂。时区很难处理,但没有错误,只有定义的行为。
  • 另外,它“超出了 R 的范围”,而只是外包给了操作系统。有些操作系统做得更好,有些做得更糟。
  • 我同意时区很复杂。您认为这是一种已定义的行为吗?请比较attributes(.Internal(as.POSIXlt(Sys.Date(), "BST")))$tzoneattributes(.Internal(as.POSIXlt(Sys.Date(), "Europe/London")))$tzone
  • 而且我的意思是 POSIX 时区是由“超出 R 的范围”外包的。感谢您澄清这一点。
  • 显然它“超出了 R 的范围”,因为根据定义,“外包给操作系统”超出了 R 的范围。R 在日期方面完全令人困惑,尤其是在 Windows 和Unix,尤其是在生产环境中具有大量时间序列的大型项目中,这也是我转向 Python (Pandas) 的主要原因之一。例如,如果您没有明确管理 Date 和 POSIX 类的时区属性,POSIXlt 和 POSIXct 将在切换到夏令时(和返回)时任意更改日期索引。一点都不明显。
【解决方案3】:

1/POSIXct和POSIXlt格式有什么区别

  • POSIXct 是自 the epoch 以来的秒数
  • POSIXlt 将日期时间拆分为 %Y-%m-%d%Y/%m/%d %H:%M:%S 或其他此类格式

【讨论】:

  • POSIXlt 不是字符串格式,而是一个列表。见unclass(as.POSIXlt(Sys.time(), "GMT"))。你是对的POSIXct,见unclass(as.POSIXct(Sys.time(), "GMT"))
  • @DanielKrizian 固定,我想。
  • 仍然不准确,POSIXlt 可以用比您建议的更多的字符串格式表示(请参阅详细信息?strptime)。相反,POSIXlt 表达的内容与 POSIXct 相同,但在人类可读的列表中。另外,is.list(as.POSIXlt(Sys.time(),"GMT"))#TRUE(POSIXct 为 FALSE)
  • @DanielKrizian 我再次编辑,所以看起来我不应该是全面的。
  • 这不是重点。请注意as.POSIXct(Sys.time(),"GMT")as.POSIXlt(Sys.time(),"GMT") 都以其中一种字符串格式在屏幕上得到printed,因此这不是POSIXlt 的显着特征。引用?POSIXltPOSIXlt is a named list of vectors。很高兴在更正后取消我的反对
猜你喜欢
  • 2016-10-07
  • 2019-11-07
  • 2015-05-13
  • 2014-11-10
  • 1970-01-01
  • 2018-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多