4

另一个与日期/时间相关的问题;-)

在你瞄准和射击之前

德国 + MS Windows + R组合有点搞砸了,因为以下会产生无效的时区:

> Sys.timezone()
[1] "MST"
Warning message:
In as.POSIXlt.POSIXct(Sys.time()) : unknown timezone 'MET-1MST'

这绝对不是 R 的错,而是 Windows。因此首先是问题;-)

问题

是否有一种简单/替代且独立于操作系统的方法来通过语言环境信息查询您当前的国家/地区,然后查找相应的时区(格式"<country>/<city>",例如"Europe/Berlin"德国)?

我还应该补充一点,我希望解决方案独立于互联网资源,例如本文/答案中所述。

问题上下文

假设您还不知道如何指定您的时区。您可能听说过有关CET/CEST等的信息,但 AFAIK 在使用基本 R 功能时并不能真正让您获得任何帮助(至少位于德国 ;-))。

您可以从RHOME 目录中的文件中获取可用 "<country>/<city>"对的列表。/share/zoneinfo/zone.tab然而,为了找到与您所在的当前国家相对应的时区,您需要知道 ISO 国家代码。

当然,我们通常会为我们的祖国这样做,但假设我们不这样做(我想以一种通用的方法结束)。下一步你要怎么做?

以下是我的“四步”解决方案,但我对此并不满意,因为

  1. 它依赖于另一个 contrib 包(ISOcodes
  2. 我无法测试它是否适用于其他地区,因为我不知道如果您在印度、俄罗斯、澳大利亚等地,信息实际上会是什么样子。

有人有更好的主意吗?此外,如果你们中的一些人在德国以外的国家/地区可以通过此操作并发布他们的语言环境信息,那就太好了Sys.getlocale()

第 1 步:获取语言环境信息

loc <- strsplit(unlist(strsplit(Sys.getlocale(), split=";")), split="=")
foo <- function(x) {
    out <- list(x[2])
    names(out) <- x[1]
    out
}
loc <- sapply(loc, foo)

> loc
$LC_COLLATE
[1] "German_Germany.1252"

$LC_CTYPE
[1] "German_Germany.1252"

$LC_MONETARY
[1] "German_Germany.1252"

$LC_NUMERIC
[1] "C"

$LC_TIME
[1] "German_Germany.1252"

第 2 步:从语言环境信息中获取国家/地区名称

country.this <- unlist(strsplit(loc$LC_TIME, split="_|\\."))[2]

> country.this 
[1] "Germany"

第三步:获取 ISO 国家代码

用于在包ISOcodescountry.this的数据集中查找相关的国家代码ISO_3166_1

require("ISOcodes")
data("ISO_3166_1")
iso  <- ISO_3166_1
idx  <- which(iso$Name %in% country.this)
code <- iso[idx, "Alpha_2"]

> code
[1] "DE"

第四步:获取时区

用于code查找可从文件导出的数据框中的时区RHOME/share/zoneinfo/zone.tab

path <- file.path(Sys.getenv("R_HOME"), "share/zoneinfo/zone.tab")    
tzones <- read.delim(
    path, 
    row.names=NULL, 
    header=FALSE,
    col.names=c("country", "coords", "name", "comments"),
    as.is=TRUE, 
    fill=TRUE, 
    comment.char = "#"
)

> tzones[which(tzones$country == code), "name"]
[4] "Europe/Berlin"
4

2 回答 2

2

特别是关于你的问题:

是否有一种简单/替代且独立于操作系统的方法可以通过语言环境信息查询您当前的国家/地区,然后查找相应的时区?

不,那里没有。这是因为有几个国家有多个时区。仅凭一个国家是无法知道时区的。

这就是为什么 TZDB 标识符采用 的形式Area/Location,而不仅仅是国家代码列表。

于 2013-06-09T19:10:04.837 回答
0

对您的工作流程进行了一些简化。

您可以使用仅检索语言环境的时间部分

Sys.getlocale("LC_TIME")

这避免了拆分字符串的需要。

lubridate 包包含一个检索 Olson 风格的时区名称的函数,因此您不必担心读取和解析zone.tab.

library(lubridate)
olson_time_zones()
于 2014-01-06T14:45:37.093 回答