常说的 Linux 系统时钟有两个
一个是硬件时钟(RTC),即BIOS时间,一般保存的是 GMT0 时间,没时区、夏令时的概念
一个是当地时钟(LTC),即我们日常经常看到的时间,比如 date 命令获取的时间,一般是在 GMT 时间的基础上增加或者减去 0 ~ 12 小时
Coordinated Universal Time,协调世界时,又称世界标准时间或世界协调时间,是最主要的世界时间标准,其以原子时秒长为基础,在时刻上尽量接近于格林尼治标准时间
Greenwich MeanTime,格林尼治时间,又称格林尼治平均时间或格林尼治标准时间,旧译格林威治标准时间,GMT 是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。英国伦敦格林尼治定为 0° 经线开始的地方,地球每 15° 经度就被分为一个时区,共分为 24 个时区,相邻时区相差一小时;例:中国北京位于东八区,GMT 时间比北京时间慢 8 小时
补充:UTC 基本上等于 GMT,世界上所有国家的时间都是以此时间为基准
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:00 | International Date Line West 国际日期变更线 |
Etc/GMT+12 |
GMT-11:00 | Midway Island, Samoa 萨摩亚时间 |
Etc/GMT+11 |
GMT-10:00 | Hawaii 夏威夷阿留申时间 |
Etc/GMT+10 |
GMT-09:30 | Marquesas 马克萨斯时间 |
Etc/GMT+9.30 ** |
GMT-09:00 | Alaska 阿拉斯加时间 |
Etc/GMT+9 |
GMT-08:00 | Pacific Time (US & Canada) 太平洋时间 |
Etc/GMT+8 |
GMT-07:00 | Arizona, Mountain America 北美山地时间 |
Etc/GMT+7 |
GMT-06:00 | Central America 北美中部时间 |
Etc/GMT+6 |
GMT-05:00 | Eastern Time (US & Canada) 北美东部时间 |
Etc/GMT+5 |
GMT-04:00 | Atlantic Time (Canada) 大西洋时间 |
Etc/GMT+4 |
GMT-03:30 | Newfoundland 纽芬兰时间 |
Etc/GMT+3.30 ** |
GMT-03:00 | Brasilia 巴西利亚时间 |
Etc/GMT+3 |
GMT-02:00 | Mid-Atlantic 大西洋中部时间 |
Etc/GMT+2 |
GMT-01:00 | Azores 亚速尔群岛时间 |
Etc/GMT+1 |
GMT+00:00 | Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London 格林尼治时间 |
Etc/GMT Etc/GMT+0 Etc/GMT-0 Etc/GMT0 |
GMT+01:00 | Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna 欧洲中部时间 |
Etc/GMT-1 |
GMT+02:00 | Jerusalem 以色列时间 |
Etc/GMT-2 |
GMT+03:00 | Moscow, St. Petersburg, Volgograd 莫斯科时间 |
Etc/GMT-3 |
GMT+03:30 | Tehran 伊朗时间 |
Etc/GMT-3.30 ** |
GMT+04:00 | Abu Dhabi, Muscat 海湾时间 |
Etc/GMT-4 |
GMT+04:30 | Kabul 阿富汗时间 |
Etc/GMT-4.30 ** |
GMT+05:00 | Islamabad, Karachi, Tashkent 巴基斯坦时间 |
Etc/GMT-5 |
GMT+05:30 | Chennai, Kolkata, Mumbai, New Delhi 印度时间 |
Etc/GMT-5.30 ** |
GMT+05:45 | Kathmandu 尼泊尔时间 |
Etc/GMT-5.45 ** |
GMT+06:00 | Astana, Dhaka 孟加拉国时间 |
Etc/GMT-6 |
GMT+06:30 | Yangon (Rangoon) 缅甸时间 |
Etc/GMT-6.30 ** |
GMT+07:00 | Bangkok, Hanoi, Jakarta 印度支那时间 |
Etc/GMT-7 |
GMT+08:00 | Beijing, Chongqing, Hong Kong, Urumqi 中国时间 |
Etc/GMT-8 |
GMT+08:30 | Pyongyang 平壤时间 |
Etc/GMT-8.30 ** |
GMT+08:45 | Eucla 澳大利亚中部西部时间 |
Etc/GMT-8.45 ** |
GMT+09:00 | Osaka, Sapporo, Tokyo 日本时间 |
Etc/GMT-9 |
GMT+09:30 | Adelaide 澳大利亚中央时间 |
Etc/GMT-9.30 ** |
GMT+10:00 | Canberra, Melbourne, Sydney 澳大利亚东部时间 |
Etc/GMT-10 |
GMT+10:30 | Lord Howe Island 豪勋爵时间 |
Etc/GMT-10.30 ** |
GMT+11:00 | Magadan, Solomon Is., New Caledonia 所罗门群岛时间 |
Etc/GMT-11 |
GMT+12:00 | Fiji, Kamchatka, Marshall Is. 斐济时间 新西兰时间 |
Etc/GMT-12 |
GMT+12:45 | Chatham Is. 查塔姆岛标准时间 |
Etc/GMT-12.45 ** |
GMT+13:00 | Nuku’alofa 汤加时间 |
Etc/GMT-13 |
GMT+14:00 | Christmas Island 莱恩群岛时间 |
Etc/GMT-14 |
注意:
再来看一下带夏令时的时区文件代表
时区 | 地区代表 | 时区文件 |
---|---|---|
GMT-12:00 | International Date Line West 国际日期变更线 |
N/A |
GMT-11:00 | Midway Island, Samoa 萨摩亚时间 |
N/A |
GMT-10:00 | Hawaii 夏威夷阿留申时间 |
America/Adak |
GMT-09:30 | Marquesas 马克萨斯时间 |
N/A |
GMT-09:00 | Alaska 阿拉斯加时间 |
America/Anchorage |
GMT-08:00 | Pacific Time (US & Canada) 太平洋时间 |
America/Los_Angeles |
GMT-07:00 | Arizona, Mountain America 北美山地时间 |
America/Denver |
GMT-06:00 | Central America 北美中部时间 |
America/Chicago |
GMT-05:00 | Eastern Time (US & Canada) 北美东部时间 |
America/New_York |
GMT-04:00 | Atlantic Time (Canada) 大西洋时间 |
America/Halifax |
GMT-03:30 | Newfoundland 纽芬兰时间 |
America/St_Johns |
GMT-03:00 | Brasilia 巴西利亚时间 皮埃尔和密克隆群岛时间 |
America/Sao_Paulo America/Miquelon |
GMT-02:00 | Mid-Atlantic 大西洋中部时间 |
N/A |
GMT-01:00 | Azores 亚速尔群岛时间 |
Atlantic/Azores |
GMT+00:00 | Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London 格林尼治时间 |
Europe/London |
GMT+01:00 | Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna 欧洲中部时间 |
Europe/Amsterdam |
GMT+02:00 | Jerusalem 以色列时间 欧洲东部时间 |
Asia/Jerusalem Europe/Kiev |
GMT+03:00 | Moscow, St. Petersburg, Volgograd 莫斯科时间 |
N/A |
GMT+03:30 | Tehran 伊朗时间 |
Asia/Tehran |
GMT+04:00 | Abu Dhabi, Muscat 海湾时间 |
N/A |
GMT+04:30 | Kabul 阿富汗时间 |
N/A |
GMT+05:00 | Islamabad, Karachi, Tashkent 巴基斯坦时间 |
N/A |
GMT+05:30 | Chennai, Kolkata, Mumbai, New Delhi 印度时间 |
N/A |
GMT+05:45 | Kathmandu 尼泊尔时间 |
N/A |
GMT+06:00 | Astana, Dhaka 孟加拉国时间 |
N/A |
GMT+06:30 | Yangon (Rangoon) 缅甸时间 |
N/A |
GMT+07:00 | Bangkok, Hanoi, Jakarta 印度支那时间 |
N/A |
GMT+08:00 | Beijing, Chongqing, Hong Kong, Urumqi 中国时间 |
N/A |
GMT+08:30 | Pyongyang 平壤时间 |
N/A |
GMT+08:45 | Eucla 澳大利亚中部西部时间 |
N/A |
GMT+09:00 | Osaka, Sapporo, Tokyo 日本时间 |
N/A |
GMT+09:30 | Adelaide 澳大利亚中央时间 |
Australia/Adelaide |
GMT+10:00 | Canberra, Melbourne, Sydney 澳大利亚东部时间 |
Australia/Melbourne |
GMT+10:30 | Lord Howe Island 豪勋爵时间 |
Australia/Lord_Howe |
GMT+11:00 | Magadan, Solomon Is., New Caledonia 所罗门群岛时间 |
N/A |
GMT+12:00 | Fiji, Kamchatka, Marshall Is. 斐济时间 新西兰时间 |
Pacific/Auckland |
GMT+12:45 | Chatham Is. 查塔姆岛标准时间 |
Pacific/Chatham |
GMT+13:00 | Nuku’alofa 汤加时间 |
N/A |
GMT+14:00 | Christmas Island 莱恩群岛时间 |
N/A |
注意:
常用的工具
这两个工具,在 Ubuntu 18.04 的机器上,默认就有
去官网:https://www.iana.org/time-zones 下载最新的 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
编译完成后的安装目录结构如下
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
# 回到 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 # 据说这个可以兼容老版本
这个工具还是挺好玩的,通过命令行交互,可以列出世界各大板块的各个国家的各个主要城市,还能看到该城市使用的是哪个时区文件
由于实际需求,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
一文搞懂Linux时区设置、自定义时区文件
一文搞懂Linux时区设置、自定义时区文件
https://www.modb.pro/db/
https://www.cnbiancheng.com/?p=1631
https://www.iana.org/time-zones
http://www.shijian.cc/shiqu/ - - 可以对照时间,验证设置的时区文件准不准
根据 tzselect 汇总了全球200多个国家或地区的时区文件,以及典型的城市代表(400多个),json 格式如下:
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" } ] } ] }