确定 FreeBSD 中当前设置的默认时区

确定 FreeBSD 中当前设置的默认时区

我知道sudo tzsetup会提示我更改 FreeBSD 上的时区设置。

➥ 如何在不进行更改的情况下查看当前时区设置?

我知道date会显示当前时间。例如:

世界标准时间 2018 年 12 月 9 日星期日 05:45:25

…我假设当前默认时区是 UTC。

但在这种情况下:

2018 年太平洋标准时间 12 月 8 日星期六 21:52:04

PST不是真正的时区。这种 2-4 个字母的代码既不是标准化的,也不是唯一的。真实时区的格式Continent/RegionEurope/AfricaAfrica/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

然后使用该信息将其编译为二进制格式齐克格式指定于tz文件

我不知道有一个内置实用程序可以直接解析该文件。但根据手头的文档,用 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.

相关内容