如何找到当前的系统时区?

新手上路,请多包涵

在 Linux 上,我需要找到当前配置的时区作为 Olson 位置。我希望我的(C 或 C++)代码可以移植到尽可能多的 Linux 系统。

例如。我住在伦敦,所以我目前的奥尔森位置是“欧洲/伦敦”。我对诸如“BST”、“EST”之类的时区 ID 感兴趣。

Debian 和 Ubuntu 有一个文件 /etc/timezone 包含此信息,但我认为我不能依赖该文件始终存在,可以吗? Gnome 有一个函数 oobs_time_config_get_timezone() 也返回正确的字符串,但我希望我的代码在没有 Gnome 的系统上工作。

那么,在 Linux 上将当前配置的时区作为 Olson 位置的最佳通用方法是什么?

原文由 alex tingle 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

很难得到可靠的答案。依靠 /etc/timezone 之类的东西可能是最好的选择。

(The variable tzname and the tm_zone member of struct tm , as suggested in other answers, typically contains an abbreviation such as GMT / BST 等,而不是问题中要求的奥尔森时间字符串)。

  • 在基于 Debian 的系统(包括 Ubuntu)上, /etc/timezone 是一个包含正确答案的文件。
  • 在某些基于 Redhat 的系统(包括至少某些版本的 CentOS、RHEL、Fedora)上,您可以使用 /etc/localtime 上的 readlink() 获取所需的信息,这是一个符号链接(例如) /usr/share/zoneinfo/Europe/London
  • OpenBSD 似乎使用与 RedHat 相同的方案。

但是,上述方法存在一些问题。 /usr/share/zoneinfo 目录还包含诸如 GMTGB 之类的文件,因此用户可以配置指向那里的符号链接。

此外,没有什么可以阻止用户在那里复制正确的时区文件而不是创建符号链接。

解决这个问题的一种可能性(这似乎适用于 Debian、RedHat 和 OpenBSD)是将 /etc/localtime 文件的内容与 /usr/share/zoneinfo 下的文件进行比较,并查看哪些匹配:

 eta:~% md5sum /etc/localtime
410c65079e6d14f4eedf50c19bd073f8  /etc/localtime
eta:~% find /usr/share/zoneinfo -type f | xargs md5sum | grep 410c65079e6d14f4eedf50c19bd073f8
410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/London
410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Belfast
410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Guernsey
410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Jersey
410c65079e6d14f4eedf50c19bd073f8  /usr/share/zoneinfo/Europe/Isle_of_Man
...
...

当然, 缺点 是这会告诉你所有与当前时区相同的时区。 (这意味着完全意义上的相同——不仅仅是“当前同时”,而且“就系统所知,总是在同一天改变他们的时钟”。)

您最好的选择可能是结合上述方法:使用 /etc/timezone 如果存在;否则尝试将 /etc/localtime 解析为符号链接;如果失败,搜索匹配的时区定义文件;如果失败 - 放弃并回家;-)

(而且我不知道上述任何内容是否适用于 AIX ……)

原文由 psmears 发布,翻译遵循 CC BY-SA 3.0 许可协议

下面的代码在 bash shell 中测试成功

  • SUSE Linux 企业服务器 11
  • Ubuntu 20.04.5 LTS
  • CentOS Linux 版本 7.9.2009

外壳代码:

 echo $(hash=$(md5sum /etc/localtime | cut -d " " -f 1) ; find /usr/share/zoneinfo -type f -print0 | while read -r -d '' f; do md5sum "$f" | grep "$hash" && break ; done) | rev | cut -d "/" -f 2,1 | rev

结果示例:

 Europe/Vienna

原文由 mik 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题