一文搞懂Linux时区设置、自定义时区文件

编程入门 行业动态 更新时间:2024-10-25 20:21:33

一文搞懂Linux<a href=https://www.elefans.com/category/jswz/34/1771311.html style=时区设置、自定义时区文件"/>

一文搞懂Linux时区设置、自定义时区文件

概念介绍

常说的 Linux 系统时钟有两个

  • 一个是硬件时钟(RTC),即BIOS时间,一般保存的是 GMT0 时间,没时区、夏令时的概念

  • 一个是当地时钟(LTC),即我们日常经常看到的时间,比如 date 命令获取的时间,一般是在 GMT 时间的基础上增加或者减去 0 ~ 12 小时

世界标准时间 (UTC)

Coordinated Universal Time,协调世界时,又称世界标准时间或世界协调时间,是最主要的世界时间标准,其以原子时秒长为基础,在时刻上尽量接近于格林尼治标准时间

格林尼治标准时间 (GMT)

Greenwich MeanTime,格林尼治时间,又称格林尼治平均时间或格林尼治标准时间,旧译格林威治标准时间,GMT 是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。英国伦敦格林尼治定为 0° 经线开始的地方,地球每 15° 经度就被分为一个时区,共分为 24 个时区,相邻时区相差一小时;例:中国北京位于东八区,GMT 时间比北京时间慢 8 小时

补充:UTC 基本上等于 GMT,世界上所有国家的时间都是以此时间为基准

夏令时 (DST)

Daylight Saving Time,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为"夏令时间"

一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏令时的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时

我国也曾经实行过夏令时,在1986年开始实行,取得了相当大的成效,每年省电相当于3个三峡,但是在6年后的1991年,考虑到多方面的因素,最终选择了取消这一制度。夏令时在中国实行了6年便停止实行,其实停止实行的原因一言蔽之就是:中国太大了。中国和英法等国相比,有两点最大的不同:一是国土面积不同,二是气候不同

设置时间

设置系统时间

/etc/localtime 这个文件是用来设置系统的时区的,将 /usr/share/zoneinfo/ 中相应的时区文件拷贝覆盖 /etc/localtime,即可修改时区设置(也可以通过软连接实现),这种修改对 date 命令是及时生效的

不论是 date 还是 hwclock 都会用到这个文件,会根据这个文件的时区设置来进行 UTC 和本地时间的换算

设置完时区之后,可以通过 date 命令来设置系统时间

设置硬件时间

设置完系统时间后,硬件 RTC 时间并没有变更,如果发生重启,系统时间又会恢复到原来的值,所以这里需要将系统时钟同步到 RTC 硬件中

通过 hwclock 命令可以完成相关的设置

世界时区代表

先来看一下不带夏令时的时区文件代表

时区地区代表时区文件
GMT-12:00International Date Line West
国际日期变更线
Etc/GMT+12
GMT-11:00Midway Island, Samoa
萨摩亚时间
Etc/GMT+11
GMT-10:00Hawaii
夏威夷阿留申时间
Etc/GMT+10
GMT-09:30Marquesas
马克萨斯时间
Etc/GMT+9.30 **
GMT-09:00Alaska
阿拉斯加时间
Etc/GMT+9
GMT-08:00Pacific Time (US & Canada)
太平洋时间
Etc/GMT+8
GMT-07:00Arizona, Mountain America
北美山地时间
Etc/GMT+7
GMT-06:00Central America
北美中部时间
Etc/GMT+6
GMT-05:00Eastern Time (US & Canada)
北美东部时间
Etc/GMT+5
GMT-04:00Atlantic Time (Canada)
大西洋时间
Etc/GMT+4
GMT-03:30Newfoundland
纽芬兰时间
Etc/GMT+3.30 **
GMT-03:00Brasilia
巴西利亚时间
Etc/GMT+3
GMT-02:00Mid-Atlantic
大西洋中部时间
Etc/GMT+2
GMT-01:00Azores
亚速尔群岛时间
Etc/GMT+1
GMT+00:00Greenwich Mean Time :
Dublin, Edinburgh, Lisbon, London
格林尼治时间
Etc/GMT
Etc/GMT+0
Etc/GMT-0
Etc/GMT0
GMT+01:00Amsterdam, Berlin, Bern,
Rome, Stockholm, Vienna
欧洲中部时间
Etc/GMT-1
GMT+02:00Jerusalem
以色列时间
Etc/GMT-2
GMT+03:00Moscow, St. Petersburg, Volgograd
莫斯科时间
Etc/GMT-3
GMT+03:30Tehran
伊朗时间
Etc/GMT-3.30 **
GMT+04:00Abu Dhabi, Muscat
海湾时间
Etc/GMT-4
GMT+04:30Kabul
阿富汗时间
Etc/GMT-4.30 **
GMT+05:00Islamabad, Karachi, Tashkent
巴基斯坦时间
Etc/GMT-5
GMT+05:30Chennai, Kolkata, Mumbai, New Delhi
印度时间
Etc/GMT-5.30 **
GMT+05:45Kathmandu
尼泊尔时间
Etc/GMT-5.45 **
GMT+06:00Astana, Dhaka
孟加拉国时间
Etc/GMT-6
GMT+06:30Yangon (Rangoon)
缅甸时间
Etc/GMT-6.30 **
GMT+07:00Bangkok, Hanoi, Jakarta
印度支那时间
Etc/GMT-7
GMT+08:00Beijing, Chongqing, Hong Kong, Urumqi
中国时间
Etc/GMT-8
GMT+08:30Pyongyang
平壤时间
Etc/GMT-8.30 **
GMT+08:45Eucla
澳大利亚中部西部时间
Etc/GMT-8.45 **
GMT+09:00Osaka, Sapporo, Tokyo
日本时间
Etc/GMT-9
GMT+09:30Adelaide
澳大利亚中央时间
Etc/GMT-9.30 **
GMT+10:00Canberra, Melbourne, Sydney
澳大利亚东部时间
Etc/GMT-10
GMT+10:30Lord Howe Island
豪勋爵时间
Etc/GMT-10.30 **
GMT+11:00Magadan, Solomon Is., New Caledonia
所罗门群岛时间
Etc/GMT-11
GMT+12:00Fiji, Kamchatka, Marshall Is.
斐济时间
新西兰时间
Etc/GMT-12
GMT+12:45Chatham Is.
查塔姆岛标准时间
Etc/GMT-12.45 **
GMT+13:00Nuku’alofa
汤加时间
Etc/GMT-13
GMT+14:00Christmas Island
莱恩群岛时间
Etc/GMT-14

注意:

  • 带 ** 号的,表示默认不存在该时区文件,需自定义,详见后文的《自定义时区文件》章节
  • 表里说的时区文件,路径前缀都是 /usr/share/zoneinfo/

再来看一下带夏令时的时区文件代表

时区地区代表时区文件
GMT-12:00International Date Line West
国际日期变更线
N/A
GMT-11:00Midway Island, Samoa
萨摩亚时间
N/A
GMT-10:00Hawaii
夏威夷阿留申时间
America/Adak
GMT-09:30Marquesas
马克萨斯时间
N/A
GMT-09:00Alaska
阿拉斯加时间
America/Anchorage
GMT-08:00Pacific Time (US & Canada)
太平洋时间
America/Los_Angeles
GMT-07:00Arizona, Mountain America
北美山地时间
America/Denver
GMT-06:00Central America
北美中部时间
America/Chicago
GMT-05:00Eastern Time (US & Canada)
北美东部时间
America/New_York
GMT-04:00Atlantic Time (Canada)
大西洋时间
America/Halifax
GMT-03:30Newfoundland
纽芬兰时间
America/St_Johns
GMT-03:00Brasilia
巴西利亚时间
皮埃尔和密克隆群岛时间
America/Sao_Paulo
America/Miquelon
GMT-02:00Mid-Atlantic
大西洋中部时间
N/A
GMT-01:00Azores
亚速尔群岛时间
Atlantic/Azores
GMT+00:00Greenwich Mean Time :
Dublin, Edinburgh, Lisbon, London
格林尼治时间
Europe/London
GMT+01:00Amsterdam, Berlin, Bern,
Rome, Stockholm, Vienna
欧洲中部时间
Europe/Amsterdam
GMT+02:00Jerusalem
以色列时间
欧洲东部时间
Asia/Jerusalem
Europe/Kiev
GMT+03:00Moscow, St. Petersburg, Volgograd
莫斯科时间
N/A
GMT+03:30Tehran
伊朗时间
Asia/Tehran
GMT+04:00Abu Dhabi, Muscat
海湾时间
N/A
GMT+04:30Kabul
阿富汗时间
N/A
GMT+05:00Islamabad, Karachi, Tashkent
巴基斯坦时间
N/A
GMT+05:30Chennai, Kolkata, Mumbai, New Delhi
印度时间
N/A
GMT+05:45Kathmandu
尼泊尔时间
N/A
GMT+06:00Astana, Dhaka
孟加拉国时间
N/A
GMT+06:30Yangon (Rangoon)
缅甸时间
N/A
GMT+07:00Bangkok, Hanoi, Jakarta
印度支那时间
N/A
GMT+08:00Beijing, Chongqing, Hong Kong, Urumqi
中国时间
N/A
GMT+08:30Pyongyang
平壤时间
N/A
GMT+08:45Eucla
澳大利亚中部西部时间
N/A
GMT+09:00Osaka, Sapporo, Tokyo
日本时间
N/A
GMT+09:30Adelaide
澳大利亚中央时间
Australia/Adelaide
GMT+10:00Canberra, Melbourne, Sydney
澳大利亚东部时间
Australia/Melbourne
GMT+10:30Lord Howe Island
豪勋爵时间
Australia/Lord_Howe
GMT+11:00Magadan, Solomon Is., New Caledonia
所罗门群岛时间
N/A
GMT+12:00Fiji, Kamchatka, Marshall Is.
斐济时间
新西兰时间
Pacific/Auckland
GMT+12:45Chatham Is.
查塔姆岛标准时间
Pacific/Chatham
GMT+13:00Nuku’alofa
汤加时间
N/A
GMT+14:00Christmas Island
莱恩群岛时间
N/A

注意:

  • N/A,表示该地区没有夏令时
  • 表里说的时区文件,路径前缀都是 /usr/share/zoneinfo/

工具介绍

常用的工具

  • zdump,以文本展示某个时区变化历史的工具
  • zic,时区编译器,可将时区定义的文本文件编译成二进制时区文件
  • tzselect,设置时区的工具

这两个工具,在 Ubuntu 18.04 的机器上,默认就有

编译

去官网: 下载最新的 timezone 压缩包

在 Ubuntu 18.04 的机器上,执行如下步骤开始编译

lzip -d tzdb-2022g.tar.lz
tar -xf tzdb-2022g.tar
mkdir out
cd tzdb-2022g/
# TOPDIR 指定目录安装,否则会安装到系统的 /usr/share/zoneinfo/ 目录下
make TOPDIR=$PWD/../out install

编译完成后的安装目录结构如下

zdump

cd ../out/usr/bin/
./zdump -v ../share/zoneinfo/America/Los_Angeles
# 报错说: No such file or directory
# 使用 strace 来跟踪看看哪里出了问题
strace ./zdump -v ../share/zoneinfo/America/Los_Angeles
# 发现是 zdump 默认会把 $TOPDIR/usr/share/zoneinfo/ 带进来
# 所以我们只需要带 America/Los_Angeles 就可以了
./zdump -v America/Los_Angeles
# 就可以看到夏令时相关的信息啦,strace 真有用# 后来研读 zdump.c 的代码,发现绝对路径也可以,第一个字符要是'/'
./zdump -v /home/xxx/out/usr/share/zoneinfo/America/Los_Angeles

zic

# 回到 tzdb-2022g 目录,当前目录就有之前编译生成的 zdump/zic 工具
# 新建个目录,拿"北美"这个文本文件,编译一下生成二进制时区文件
mkdir my_tz_file
./zic -d ./my_tz_file/ northamerica
# 生成的二进制时区文件都在这个新建的文件夹里了
# 再用 zdump 试一下
./zdump -v /home/xxx/tzdb-2022g/my_tz_file/America/Los_Angeles
# 也是没问题的,但有一点疑惑
# 我们自己生成的 Los_Angeles 文件,文件大小跟系统的有出入
ls -lh ./my_tz_file/America/Los_Angeles
# 1.3K
ls -lh /usr/share/zoneinfo/America/Los_Angeles
# 2.8K# 仔细看 zic 的说明文档才发现,如果要跟系统的文件一样大,需要加 -b fat 参数
./zic -b fat -d ./my_tz_file/ northamerica
# 据说这个可以兼容老版本

tzselect

这个工具还是挺好玩的,通过命令行交互,可以列出世界各大板块的各个国家的各个主要城市,还能看到该城市使用的是哪个时区文件

自定义时区文件

由于实际需求,Linux 系统自带的时区文件无法满足需要,上面介绍的世界时区是带夏令时规则的,如果我们不想考虑夏令时,可以使用 /usr/share/zoneinfo/Etc 目录下的时区文件,但是发现该目录缺少了一些非整数的时区文件

从上面介绍的世界时区代表可知,世界上存在着一些特殊的非整数时区,罗列如下

GMT-09:30
GMT-03:30
GMT+03:30
GMT+04:30
GMT+05:30
GMT+05:45
GMT+06:30
GMT+08:30
GMT+08:45
GMT+09:30
GMT+10:30
GMT+12:45

所以需要我们手动编辑 tzdb-2022g 目录下的 etcetera 文本文件,添加一段,如下红框部分

需要注意的是,文本文件最后需要一行空白行结尾

再用 zic 编辑器生成对应的时区文件,就可以拿去用啦

mkdir my_tz_file_etc
./zic -b fat -d ./my_tz_file_etc/ etcetera

参考

/?p=1631

/ - - 可以对照时间,验证设置的时区文件准不准

附录

根据 tzselect 汇总了全球200多个国家或地区的时区文件,以及典型的城市代表(400多个),json 格式如下:

  • gmt 表示该城市使用的时区(没有夏令时)
  • dst 表示该城市夏令时(如果有的话)的时区文件


Africa.json 片段如下,想获取完整版的可私信笔者获取

{"countries" : [{"country" : "Algeria","cities" : [{"city" : "Algiers","gmt" : "Etc/GMT-1","dst" : "Africa/Algiers"}]},{"country" : "Angola","cities" : [{"city" : "Luanda","gmt" : "Etc/GMT-1","dst" : "Africa/Luanda"}]},{"country" : "Benin","cities" : [{"city" : "Porto-Novo","gmt" : "Etc/GMT-1","dst" : "Africa/Porto-Novo"}]},{"country" : "Botswana","cities" : [{"city" : "Gaborone","gmt" : "Etc/GMT-2","dst" : "Africa/Gaborone"}]},{"country" : "Burkina Faso","cities" : [{"city" : "Ouagadougou","gmt" : "Etc/GMT0","dst" : "Africa/Ouagadougou"}]},{"country" : "Burundi","cities" : [{"city" : "Bujumbura","gmt" : "Etc/GMT-2","dst" : "Africa/Bujumbura"}]},{"country" : "Cameroon","cities" : [{"city" : "Douala","gmt" : "Etc/GMT-1","dst" : "Africa/Douala"}]},{"country" : "Central African Rep.","cities" : [{"city" : "Bangui","gmt" : "Etc/GMT-1","dst" : "Africa/Bangui"}]},{"country" : "Chad","cities" : [{"city" : "Ndjamena","gmt" : "Etc/GMT-1","dst" : "Africa/Ndjamena"}]},{"country" : "Congo (Dem. Rep.)","cities" : [{"city" : "Lubumbashi","gmt" : "Etc/GMT-2","dst" : "Africa/Lubumbashi"},{"city" : "Kinshasa","gmt" : "Etc/GMT-1","dst" : "Africa/Kinshasa"}]},{"country" : "Congo (Rep.)","cities" : [{"city" : "Brazzaville","gmt" : "Etc/GMT-1","dst" : "Africa/Brazzaville"}]}]
}

更多推荐

一文搞懂Linux时区设置、自定义时区文件

本文发布于:2024-03-04 21:22:55,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1710455.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:时区   自定义   一文   文件   Linux

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!