【问题标题】:Understanding timezone strings in R了解 R 中的时区字符串
【发布时间】:2016-09-09 08:42:41
【问题描述】:

我无法理解 R 中如何处理时区字符串以及为什么 Sys.time() 使用与 Sys.timezone() 不同的字符串?

Sys.time() 返回:

[1]“2016-05-13 10:17:04 CEST”

as.POSIXct(Sys.time()) 工作:

[1]“2016-05-13 10:17:11 CEST”

as.POSIXct("2016-05-1 10:15:21 CEST") 也可以:

[1]“2016-05-01 10:15:21 CEST”

但是,as.POSIXct("2016-05-1 10:15:21", tz = "CEST") 确实工作:

[1]“2016-05-01 10:15:21 GMT”
警告信息:
1: 在 strptime(xx, f 2:在 as.POSIXct.POSIXlt(x) 中:未知时区“CEST”
3:在 strptime(x, f, tz = tz) 中:未知时区“CEST”
4:在 as.POSIXct.POSIXlt(as.POSIXlt(x, tz, ...), tz, ...) 中:未知时区 'CEST'
5:在 as.POSIXlt.POSIXct(x, tz) 中:未知时区 'CEST'

我知道我可以通过以下方式解决问题:

Sys.timezone(location = TRUE)

[1]“欧洲/柏林”

然后as.POSIXct("2016-05-1 10:15:21", tz = Sys.timezone(location = TRUE)) 返回:

[1]“2016-05-01 10:15:21 CEST”

但我想了解为什么上面的方法会这样? 假设我有来自不同时区(比如纽约)的数据,我怎么知道要使用哪个字符串?

编辑: Matt 和 Adams 的链接提供了第二个问题的答案:可以在 Wikipedia 或 lubridate::olson.time.zones 上查看时区。

但是,主要问题仍未得到解答:为什么“2016-05-01 10:15:21 CEST”是有效的POSIXct class,而as.POSIXct("2016-05-1 10:15:21", tz = "CEST") 是不可能的。

【问题讨论】:

标签: r timezone


【解决方案1】:

指定的时区必须是来自IANA TZ Database 的时区。你可以找到a list of all supported time zones hereCEST 不在列表中。

一般来说,TZDB 中的标识符有以下几种形式:

  • 基于位置的区域,格式为Area/Locality,例如America/Los_AngelesEurope/ParisPacific/Honolulu
    • 这是最受青睐的格式,应尽可能使用。
    • 有的有两个以上的部分,比如America/Indiana/Knox
  • 具有固定偏移量的管理区域,例如Etc/UTCEtc/GMT-3Etc/GMT+5
    • 除 UTC 和 GMT 外,这些主要用于海上船舶。在陆地上几乎不需要它们。
    • 由于遗留原因,这些字符串中的偏移量符号反转。
  • 较旧的国家/地区特定区域,例如US/CentralCanada/AtlanticEgypt
    • 这些应被视为已弃用。它们在很久以前曾经是区域条目,但现在只是为了向后兼容而使用的“链接”。
  • 一些更流行的 POSIX 样式时区,例如 EST5EDT
    • 也是为了向后兼容。不要使用这些。
    • 有关详细信息,请参阅有关 posix 时区in the timezone tag wiki 的部分。
  • 一些常见的时区缩写,例如CETEST
    • 同样,不要使用这些。
    • 请参阅this list on Wikipedia 并注意有很多重复的条目,使缩写有些模糊。例如,CST 可能是北美的中部标准时间,也可能属于古巴、中国或澳大利亚。
    • 尽管CEST 乍一看可能并不模棱两可,但请考虑到许多不同的 IANA 时区使用相同的缩写,即使它们在历史上的某个时刻可能有所不同。

【讨论】:

  • 感谢 (+1) 您对时区的详尽回答。但这仍然让我想知道为什么“2016-05-01 10:15:21 CEST”是有效的POSIXct classas.POSIXct("2016-05-1 10:15:21", tz = "CEST") 不起作用。
  • 除了tz 必须是有效的 olson 标识符之外,找不到 precise 引用,但其他形式支持的缩写可能是特定于实现的,或者也许被忽略了。或者他们可能正在对缩写的子集进行粗略匹配,或者从输出端获取它们并仅获取匹配的第一个。我没有看到关于这一点的硬性规范。
  • 尝试其他缩写,看看会发生什么。例如,BST 有什么作用?你有英国夏令时吗?还是孟加拉国标准时间?
【解决方案2】:

CEST 可能代表中欧夏季时间。 因此,在夏令时,CET 变为 CEST,而在冬季则不会:

as.POSIXct(c("2016-1-1 13:00", "2016-3-1 13:00",
             "2016-5-1 13:00", "2016-6-1 13:00",
             "2016-9-1 13:00","2016-11-1 13:00"), tz="CET") 

返回:

 "2016-01-01 13:00:00 CET" "2016-03-01 13:00:00 CET"  "2016-05-01 13:00:00 CEST"  
 "2016-06-01 13:00:00 CEST" "2016-09-01 13:00:00 CEST" "2016-11-01 13:00:00 CET"

但是,正如@Matt_Johnson 解释的那样,CEST 不在官方时区,
所以as.POSIXct("2016-1-1 13:00, tz="CEST") 失败了。

奇怪的是,字符串中的 CEST 是可以接受的,即使时间是 夏令时之外:

as.POSIXct("2016-1-1 13:00 CEST")
[1] "2016-01-01 13:00:00 CET"

来自as.POSIXctstrptime 的帮助文件在这里没有提供任何解释。

【讨论】:

    【解决方案3】:

    有时我希望世界只使用单一的度量单位标准,无论是时间、长度、温度等。但直到那一天,来自 rstudio 的这个链接是处理时间的最佳文章之一:https://rstudio-pubs-static.s3.amazonaws.com/28038_1bcb9aa80ca84f27ace07d612872861a.html

    专门针对您的问题

    library(lubridate)
    x <- as.POSIXct("2016-05-1 10:15:21", tz = "America/New_York")
    with_tz(x, tz="Europe/Berlin")
    [1] "2016-05-01 16:15:21 CEST"
    

    【讨论】:

    • 感谢链接,确实很有用。它确实回答了我的第二个问题,如何从 lubridate 包中找到时区字符串:olson_time_zones()。但是我仍然不明白为什么as.POSIXct("2016-05-1 10:15:21 CEST") 有效而as.POSIXct("2016-05-1 10:15:21", tz = "CEST") 无效。
    猜你喜欢
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    • 2018-12-07
    相关资源
    最近更新 更多