我知道sudo tzsetup
会提示我更改 FreeBSD 上的时区设置。
➥ 如何在不进行更改的情况下查看当前时区设置?
我知道date
会显示当前时间。例如:
世界标准时间 2018 年 12 月 9 日星期日 05:45:25
…我假设当前默认时区是 UTC。
但在这种情况下:
2018 年太平洋标准时间 12 月 8 日星期六 21:52:04
这PST
不是真正的时区。这种 2-4 个字母的代码既不是标准化的,也不是唯一的。真实时区的格式Continent/Region
如Europe/Africa
或Africa/Tunis
(请参阅维基百科)。
如何查看默认设置的真实时区?
此贴提到使用环境变量TZ
。
export TZ=America/Los_Angeles
但我的FreeBSD 11.2机器没有这样的变量集。所以我怀疑这不是驱动因素。
答案1
TLDR 的答案是:
$ POSIXTZ=$(tail -n1 /etc/localtime)
$ echo $POSIXTZ
CET-1CEST,M3.5.0,M10.5.0/3
$ TZNAME=$(find /usr/share/zoneinfo | while read fname; do cmp -s /etc/localtime "$fname" && echo "$fname" | cut -c 21- ; done)
$ echo $TZNAME
Europe/Copenhagen
当前时区存储在文件中/etc/localtime
。正如@Kusalananda 所说,这可以是一个符号链接。但正如 @JdeBP 暗示的那样,在 FreeBSD 上,该文件通常是在/usr/share/zoneinfo
安装过程中复制的。
这些文件来源于文本描述贡献/tzdata
我不知道有一个内置实用程序可以直接解析该文件。但根据手头的文档,用 C 语言编写应该很容易。如果我们想坚持使用开箱即用的东西,我们可以使用 来查看它hexdump
。
hexdump -v -C /etc/localtime
或者,如果我们只想查看魔术标记:
$ hexdump -v -s 0 -n 5 -e '1/5 "%s\n"' /etc/localtime
TZif2
或者字段:
tzh_ttisgmtcnt The number of UTC/local indicators stored in the file.
tzh_ttisstdcnt The number of standard/wall indicators stored in the file.
tzh_leapcnt The number of leap seconds for which data is stored in the file.
tzh_timecnt The number of ``transition times'' for which data is stored in the file.
tzh_typecnt The number of ``local time types'' for which data is stored in the file (must not be zero).
tzh_charcnt The number of characters of ``time zone abbreviation strings'' stored in the file.
使用:
hexdump -v -s 19 -n 4 -e '"tzh_ttisgmtcnt: " 1/4 "%9u\n"' /etc/localtime
hexdump -v -s 23 -n 4 -e '"tzh_ttisstdcnt: " 1/4 "%9u\n"' /etc/localtime
hexdump -v -s 27 -n 4 -e '"tzh_leapcnt: " 1/4 "%9u\n"' /etc/localtime
hexdump -v -s 31 -n 4 -e '"tzh_timecnt: " 1/4 "%9u\n"' /etc/localtime
hexdump -v -s 35 -n 4 -e '"tzh_typecnt: " 1/4 "%9u\n"' /etc/localtime
hexdump -v -s 39 -n 4 -e '"tzh_charcnt: " 1/4 "%9u\n"' /etc/localtime
我的案例结果:
tzh_ttisgmtcnt: 0
tzh_ttisstdcnt: 6
tzh_leapcnt: 6
tzh_timecnt: 0
tzh_typecnt: 133
tzh_charcnt: 6
然后我们进行以下数学运算来找出第一个ttinfo
开始的位置:
43 + (tzh_timecnt * 4) + (tzh_timecnt * 1)
43 + (0 * 4) + (0 * 1) = 43
车轮慢慢落下:
$ hexdump -v -s 43 -n 6 -e '"ttinfo:\n tt_gmtoff: " 1/4 "%9u\n tt_isdst: " 1/1 "%1d\n tt_abbrind: " 1/1 "%1u\n"' /etc/localtime
ttinfo:
tt_gmtoff: 2350816009
tt_isdst: 96
tt_abbrind: 155
有了这些数字,我可能有点偏离。这确实是一种受虐狂的处理方式。所以我在差点找到黄金时就停下来了tt_abbrind
但如果我们看一下底部tz文件规范我们发现这个小金块:
第二个标头和数据之后是一个换行符封闭的 POSIX-TZ 环境变量样式字符串,用于处理文件中存储的最后一次转换时间之后的时刻(如果没有 POSIX 表示,则换行符之间没有任何内容)对于这样的时刻)。
所以它很简单:
$ tail -n1 /etc/localtime
CET-1CEST,M3.5.0,M10.5.0/
当你仔细观察时,你会发现它/etc/localtime
不包含任何Continent/Region
设置!但当文件被复制时,/usr/share/zoneinfo
您可以比较它们并找到可能的文件。我还没有深入到确认是否/usr/share/zoneinfo
可能包含重复项。但对我来说 - 这很有效:
$ find /usr/share/zoneinfo | while read fname; do cmp -s /etc/localtime "$fname" && echo "$fname" | cut -c 21- ; done
Europe/Copenhagen
我们遍历所有文件/usr/share/zoneinfo
并将它们与/etc/localtime
.cmp
使用-s
参数不会显示任何内容,只会使用值退出。如果该值为零,我们将打印名称。打印名称时,我们使用cut
删除前 21 个字符来获取Continent/Region
答案2
tzsetup
如果此时区已设置当前时区名称保存在/var/db/zoneinfo
:
$ sudo tzsetup Europe/Berlin
$ cat /var/db/zoneinfo
Europe/Berlin
这允许重新安装时区文件/etc/localtime
:
$ sudo rm /etc/localtime
$ sudo tzsetup -r
$ ls -l /etc/localtime
-r--r--r-- 1 root wheel 2309 Feb 15 10:59 /etc/localtime
如果时区文件是手动复制的,而不是使用,tzsetup
那么您必须找到相应源文件的名称,如下所示解释了作者:克劳斯·安徒生:
$ cd /usr/share/zoneinfo && find . -type f -exec cmp -s /etc/localtime '{}' \; -print | sed 's,^\./,,'
Europe/Berlin
我已经使用 FreeBSD 11.3 和 12.1 版本对此进行了测试。
答案3
通过检查符号链接可以明显看出 FreeBSD、OpenBSD 和 NetBSD 上使用的当前默认时区/etc/localtime
。它将指向 下的时区定义文件/usr/share/zoneinfo
。
例如:
$ ls -l /etc/localtime
lrwxr-xr-x 1 root wheel 36 Aug 11 13:51 /etc/localtime -> /usr/share/zoneinfo/Europe/Stockholm
答案4
简单的跨平台解决方案就是使用date
!
$ date +"%Z"
CET
$ date +"%z"
+0100
就您而言,您可能会再次获得 PST - 但我认为这个答案对于那些能够接受这一点的人来说也很重要。这会考虑到环境中是否设置了 TZ。在实际使用中 - offset 通常比Continent/Region
.