又一个与日期/时间相关的问题;-)
瞄准和射击之前
德国+ 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 目录中的/share/zoneinfo/zone.tab
文件中获取可用"<country>/<city>"
对的列表。但是,为了找到与您当前所在国家/地区相对应的时区,您需要知道ISO国家/地区代码。
通常为我们的祖国做,但让我们假设我们没有(我想最终采用一种通用方法)。你接下来要做什么?
以下是我的"四步"解决方案,但我对此并不满意,因为
- 它依赖于另一个贡献包(ISOcodes)
- 我无法测试它是否适用于其他区域设置,因为我不知道如果您在印度、俄罗斯、澳大利亚等地,这些信息实际上会是什么样子。
有人有更好的主意吗?另外,如果德国以外的一些国家的一些人可以运行此内容并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"
第 3 步:获取 ISO 国家/地区代码
使用country.this
在软件包 ISO 代码的数据集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"
第 4 步:获取时区
使用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"
特别是关于您的问题:
有没有一种简单/替代且独立于操作系统的方法可以通过区域设置信息查询您当前的国家/地区,然后查找相应的时区?
不 - 没有。 这是因为有几个国家/地区有多个时区。 仅从国家/地区就无法知道时区。
这就是为什么TZDB标识符采用Area/Location
的形式,而不仅仅是国家代码列表。
对工作流程的一些简化。
您可以使用
Sys.getlocale("LC_TIME")
这避免了需要拆分字符串。
润滑包包含检索奥尔森式时区名称的功能,因此您不必担心读取和解析zone.tab
。
library(lubridate)
olson_time_zones()