关于时区:通用时区你应该知道的数据库时区知识

39次阅读

共计 9442 个字符,预计需要花费 24 分钟才能阅读完成。

摘要:咱们深刻理解一下通用时区数据库的组织规定,以及时区和夏令时到底是如何保护的,GaussDB(DWS)中又是如何应用的。

本文分享自华为云社区《你应该晓得的时区常识之通用时区数据库》,原文作者:leapdb。

1. 背景介绍

接下来,咱们深刻理解一下通用时区数据库的组织规定,以及时区和夏令时到底是如何保护的,GaussDB(DWS)中又是如何应用的。

2. 通用时区数据库介绍

各地的时区和夏令时规定由各自的政府独立治理,他们常常在无限的告诉下进行变更。而且他们历史数据和将来打算也只是断断续续的记录下来。通用时区数据库试图组织和整顿这一畛域相干的数据。

时区数据库,通常称为 tz, tzdata 或 zoneinfo,是一组蕴含大量代码和数据用来示意寰球许多有代表性的地点的本地工夫的历史信息,他会依据各个政体对时区边界和夏令时规定的扭转而不定期的更新。数据库中每一个条目都代表这自 1970 年以来被宽泛认可的民用时钟的时区信息。该数据库被很多我的项目援用,比方:the GNU C Library (used in GNU/Linux), Android, FreeBSD, NetBSD, OpenBSD, Chromium OS, Cygwin, MariaDB, MINIX, MySQL, webOS, AIX, BlackBerry 10, iOS, macOS, Microsoft Windows, OpenVMS, Oracle Database, 和 Oracle Solaris。GaussDB(DWS)同其它宽泛应用的软件产品一样,也是采纳了 IANA 保护的通用时区数据。

该数据库由 David Olson 创建,由 Paul Eggert 进行编辑和保护。因此有些中央也将其称作 Olson 数据库。它的显著特色是由 Paul Eggert 设计的一套通用时区命名规定,每个时区依照“区域 / 地位”格局,失去一个独有的名称,例如“America/New_York”。英文地名中的空格用下划线“_”代替,连词符“-”只在英文地名自身蕴含时应用。时区数据库目前广泛有两个叫法 Olson 时区数据库或 IANA 时区数据库。

奥尔森(Olson)的数据有所变动,局部起因是奥尔森(AD Olson)行将退休,局部起因是针对维护者的版权侵权提起了诉讼(现已撤销)。2011 年 10 月 14 日,国内互联网名称与名称调配机构(IANA)接管了时区数据库的保护工作。它会定期进行更新以反映各政治实体对时区边界、UTC 差值和夏令时规定的更改。对 tz 的更新遵循 BCP 175 流程进行治理。

常常有一些国家变更时区规定,IANA 每年都会公布最新的时区数据和解析源码库。IANA 提供三种办法对时区数据库的拜访:

  1. https://www.iana.org/time-zones
  2. ftp://ftp.iana.org/tz/
  3. rsync://http://rsync.iana.org/tz/

时区数据库中蕴含各大洲原始的时区定义的文本文件和解析这些文本文件的代码文件。

2.1 通用时区数据库源码

相干材料:

源码托管地址:https://github.com/eggert/tz
时区数据库的介绍 https://data.iana.org/time-zones/tz-link.html
时区数据库原理及应用 https://data.iana.org/time-zones/theory.html

下载办法:

mkdir tzdb
cd tzdb
wget https://www.iana.org/time-zones/repository/tzcode-latest.tar.gz #下载最新解析时区文本定义的代码文件
wget https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz #下载最新时区定义的文本文件
gzip -dc tzcode-latest.tar.gz | tar -xf -
gzip -dc tzdata-latest.tar.gz | tar -xf -
#或者下载代码 + 数据的残缺压缩包
wget https://www.iana.org/time-zones/repository/tzdb-latest.tar.lz #下载代码 + 数据的残缺时区数据库
lzip -dc tzdb-latest.tar.lz | tar -xf -

代码构造:

时区数据库中蕴含的时区定义文件(文本文件):
africa antarctica asia australasia europe northamerica southamerica

时区数据库中蕴含的代码文件(用于解析时区定义文件)
asctime.c date.c difftime.c localtime.c strftime.c zdump.c zic.c

装置目录构造:

编译实现后的装置目录构造如下

cd tzdb-2020a
make TOPDIR=$HOME/tzdir install

leap@gaussdb:~> ./sbin/tree -L 3 tzdir/ | more
tzdir/
├── etc
│   └── localtime    #本地时区文件
└── usr
    ├── bin
    │   ├── tzselect #设置时区的工具
    │   └── zdump    #以文本展现某个时区变动历史的工具
    ├── lib
    │   └── libtz.a  #解析时区文件的动态库文件
    ├── sbin
    │   └── zic      #时区编译器,可将时区定义的文本文件编译成二进制时区文件
    └── share
        ├── man
        ├── zoneinfo #编译好的各个时区文件
        ├── zoneinfo-leaps
        └── zoneinfo-posix -> zoneinfo

#IANA 的工夫数据库被 the GNU C Library (used in GNU/Linux)采纳,因而 install 后的目录也按 linux 的系统目录来组织。

代码中的 zic.c 是一个将时区定义的原始文本文件解析成二进制时区文件的工具。如果一个软件产品须要从 IANA 获取最新时区数据的话,须要同时获取源码和数据,并生成 zic 解析器将时区数据生成时区文件给软件产品应用。时区文件的解析代码在 localtime.c 中

2.2 时区原始数据的规定及保护办法

时区数据库的 RAW 文件,是依照肯定的规定组织的文本文件。样例如下:

该规定设计的很迷信,能记录时区及夏令时变更的历史信息。应用该通用时区库能主动的转换历史工夫,也因而该库被宽泛采纳。

这里介绍一下莫斯科的时区定义

Zone  NAME              STDOFF  RULES  FORMAT   [UNTIL]
Zone Europe/Moscow       2:30:17 -      LMT     1880
                         2:30:17 -      MMT     1916 Jul  3 # Moscow Mean Time
                         2:31:19 Russia %s      1919 Jul  1  0:00u
                         3:00   Russia  %s      1921 Oct
                         3:00   Russia  MSK/MSD 1922 Oct
                         2:00   -       EET     1930 Jun 21
                         3:00   Russia  MSK/MSD 1991 Mar 31  2:00s
                         2:00   Russia  EE%sT   1992 Jan 19  2:00s
                         3:00   Russia  MSK/MSD 2011 Mar 27  2:00s
                         4:00   -       MSK     2014 Oct 26  2:00s
                         3:00   -       MSK
  • 1992 年 1 月 19 日凌晨 2 点到 2011 年 03 月 27 日凌晨 2 点,采纳东三区
  • 2011 年 3 月 27 日凌晨 2 点到 2014 年 10 月 26 日凌晨 2 点,采纳东四区
  • 2014 年 10 月 26 日凌晨 2 点当前采纳东三区

如何浏览时区数据库的 RAW 文件 https://data.iana.org/time-zo…
VSCode 的 Zoneinfo 插件能够通过语法高亮的形式查看时区数据的 RAW 文件

时区数据库的基本功能 是提供 时区数据原始文件 和一个将 时区数据原始文件 转换成 时区文件 的一个编译器:zic。

能够通过 man zic 理解时区文件编译器(将时区定义文本文件编译成二进制时区数据文件)的应用

3. 通用时区数据库应用

每个时区名的具体定义都存在于时区文件中,比方:/etc/localtime。
操作系统反对的时区文件存储在 /usr/share/zoneinfo/ 目录下。
咱们数据库反对的时区文件存储在 share/timezone 目录下。

时区文件有对立约定的格局要求(来自 IANA 保护的时区数据库),能够应用 info tzfile 查看。时区文件固定结尾构造:

struct tzhead
{char        tzh_magic[4];    /* TZ_MAGIC,固定在结尾的特色字符 "TZif" 来标识时区文件 */
    char        tzh_version[1]; /* '\0' or '2' or '3' as of 2013,版本信息 */
    char        tzh_reserved[15];    /* reserved; must be zero */
    char        tzh_ttisutcnt[4];    /* coded number of trans. time flags 保留在文件中的 UTC/local 指示器数目 */
    char        tzh_ttisstdcnt[4];    /* coded number of trans. time flags 保留在文件中的 standard/wall 指示器数目 */
    char        tzh_leapcnt[4]; /* coded number of leap seconds 其值保留在文件中的 leap second 的数目 */
    char        tzh_timecnt[4]; /* coded number of transition times 其值保留在文件中的 "变动工夫" 数目 */
    char        tzh_typecnt[4]; /* coded number of local time types 其值保留在文件中的 "本地工夫类型" 数目(非零!)*/
    char        tzh_charcnt[4]; /* coded number of abbr. chars 保留在文件中的 "时区简写符" 数目 */
};

跟在下面这些头部后的是 tzh_timecnt 个 ” 规范 ” 字节程序的四字节 long 类型值, 以升序排序. 每个值均作为一个变动工夫(就像 time(2) 的返回), 零碎依赖这些值来计算本地工夫变动.

而在此之后的是 tzh_timecnt 个 unsigned char 类型的一字节值, 这些值指出了文件中形容的多种 ” 本地工夫 ” 类型中哪一个与具备雷同索引的变动工夫相干. 这些值可作为 ttinfo 构造数组的索引.

而 ttinfo 构造在文件中随后就有定义, 形容如下:

struct ttinfo {
long tt_gmtoff;
int tt_isdst;
unsigned int tt_abbrind;
};
构造包含一个 ” 规范 ” 字节程序的四字节 long 类型值 tt_gmtoff,
以及一个一字节的 tt_isdst
和一个一字节的 tt_abbrind.
在每个构造里, tt_gmtoff 给出了要被加到 UTC 的工夫, 以秒为单位,
tt_isdst 表明 tm_isdst 是否可通过 localtime (3) 设置,
而 tt_abbrind 可作为时区简写符的数组索引, 该数组在文件中跟在 ttinfo 构造前面.

这样就有 tzh_leapcnt 个规范字节程序的四字节对, 每个四字节对的第一个值给出一个 leap second 产生的工夫, 就如 time(2) 的返回; 每个四字节对的第二个值给出给定工夫之后所实现的总的 leap second 数. 四字节对按工夫的升序排序.

同样有 tzh_ttisstdcnt 个 standard/wall 指示器, 每个保留了一个一字节值; 这些指示器指出了变动工夫 (与本地工夫类型相干) 是否被阐明为 standard time 或者 wall clock time, 以及当一个时区文件被用于解决 POSIX 格局时区环境变量时是否应用变动工夫.

最初, 有 tzh_ttisgmtcnt 个 UTC/local 指示器, 每个保留了一个一字节值; 这些指示器指出了变动工夫 (与本地工夫类型相干) 是否被阐明为 UTC 或者 local time, 以及当一个时区文件被用于解决 POSIX 格局时区环境变量时是否应用变动工夫.

如果 tzh_timecnt 等于零或者工夫参数比文件记录的第一个变动工夫小的话, Localtime 就应用文件中的第一个规范工夫 ttinfo, 或者在没有规范工夫构造是就间接应用第一个 ttinfo 构造.

能够通过 man zdump dump 二进制时区数据文件,理解如何查看一个时区的变更历史

./zdump -V Asia/Chongqing | more
Asia/Chongqing  Sat Dec 31 16:53:39 1927 UT = Sat Dec 31 23:59:59 1927 LMT isdst=0 gmtoff=25580
Asia/Chongqing  Sat Dec 31 16:53:40 1927 UT = Sat Dec 31 23:53:40 1927 LONT isdst=0 gmtoff=25200
Asia/Chongqing  Wed Apr 30 16:59:59 1980 UT = Wed Apr 30 23:59:59 1980 LONT isdst=0 gmtoff=25200
Asia/Chongqing  Wed Apr 30 17:00:00 1980 UT = Thu May  1 01:00:00 1980 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat May  3 15:59:59 1986 UT = Sat May  3 23:59:59 1986 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat May  3 16:00:00 1986 UT = Sun May  4 01:00:00 1986 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 13 14:59:59 1986 UT = Sat Sep 13 23:59:59 1986 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 13 15:00:00 1986 UT = Sat Sep 13 23:00:00 1986 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat Apr 11 15:59:59 1987 UT = Sat Apr 11 23:59:59 1987 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat Apr 11 16:00:00 1987 UT = Sun Apr 12 01:00:00 1987 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 12 14:59:59 1987 UT = Sat Sep 12 23:59:59 1987 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 12 15:00:00 1987 UT = Sat Sep 12 23:00:00 1987 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat Apr  9 15:59:59 1988 UT = Sat Apr  9 23:59:59 1988 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat Apr  9 16:00:00 1988 UT = Sun Apr 10 01:00:00 1988 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 10 14:59:59 1988 UT = Sat Sep 10 23:59:59 1988 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 10 15:00:00 1988 UT = Sat Sep 10 23:00:00 1988 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat Apr 15 15:59:59 1989 UT = Sat Apr 15 23:59:59 1989 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat Apr 15 16:00:00 1989 UT = Sun Apr 16 01:00:00 1989 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 16 14:59:59 1989 UT = Sat Sep 16 23:59:59 1989 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 16 15:00:00 1989 UT = Sat Sep 16 23:00:00 1989 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat Apr 14 15:59:59 1990 UT = Sat Apr 14 23:59:59 1990 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat Apr 14 16:00:00 1990 UT = Sun Apr 15 01:00:00 1990 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 15 14:59:59 1990 UT = Sat Sep 15 23:59:59 1990 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 15 15:00:00 1990 UT = Sat Sep 15 23:00:00 1990 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat Apr 13 15:59:59 1991 UT = Sat Apr 13 23:59:59 1991 CST isdst=0 gmtoff=28800
Asia/Chongqing  Sat Apr 13 16:00:00 1991 UT = Sun Apr 14 01:00:00 1991 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 14 14:59:59 1991 UT = Sat Sep 14 23:59:59 1991 CDT isdst=1 gmtoff=32400
Asia/Chongqing  Sat Sep 14 15:00:00 1991 UT = Sat Sep 14 23:00:00 1991 CST isdst=0 gmtoff=28800

因为我国从 1991 年开始勾销了夏令时,所以就不再变动。

4. GaussDB(DWS)中如何应用时区数据

为了国内用户的使用方便,GaussDB(DWS)依据 IANA 的定义的语法规定,在外部帮忙用户定义了 Asia/Beijing 时区,其定义与 PRC 时区定义统一。位于按装目录下的 timezone/Asia/Beijing

查看 Asia/Beijing 的具体定义:

./zdump -V Asia/Beijing
Asia/Beijing  Sat May  3 15:59:59 1986 UT = Sat May  3 23:59:59 1986 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat May  3 16:00:00 1986 UT = Sun May  4 01:00:00 1986 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 13 14:59:59 1986 UT = Sat Sep 13 23:59:59 1986 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 13 15:00:00 1986 UT = Sat Sep 13 23:00:00 1986 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat Apr 11 15:59:59 1987 UT = Sat Apr 11 23:59:59 1987 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat Apr 11 16:00:00 1987 UT = Sun Apr 12 01:00:00 1987 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 12 14:59:59 1987 UT = Sat Sep 12 23:59:59 1987 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 12 15:00:00 1987 UT = Sat Sep 12 23:00:00 1987 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat Apr  9 15:59:59 1988 UT = Sat Apr  9 23:59:59 1988 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat Apr  9 16:00:00 1988 UT = Sun Apr 10 01:00:00 1988 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 10 14:59:59 1988 UT = Sat Sep 10 23:59:59 1988 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 10 15:00:00 1988 UT = Sat Sep 10 23:00:00 1988 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat Apr 15 15:59:59 1989 UT = Sat Apr 15 23:59:59 1989 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat Apr 15 16:00:00 1989 UT = Sun Apr 16 01:00:00 1989 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 16 14:59:59 1989 UT = Sat Sep 16 23:59:59 1989 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 16 15:00:00 1989 UT = Sat Sep 16 23:00:00 1989 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat Apr 14 15:59:59 1990 UT = Sat Apr 14 23:59:59 1990 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat Apr 14 16:00:00 1990 UT = Sun Apr 15 01:00:00 1990 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 15 14:59:59 1990 UT = Sat Sep 15 23:59:59 1990 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 15 15:00:00 1990 UT = Sat Sep 15 23:00:00 1990 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat Apr 13 15:59:59 1991 UT = Sat Apr 13 23:59:59 1991 CST isdst=0 gmtoff=28800
Asia/Beijing  Sat Apr 13 16:00:00 1991 UT = Sun Apr 14 01:00:00 1991 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 14 14:59:59 1991 UT = Sat Sep 14 23:59:59 1991 CDT isdst=1 gmtoff=32400
Asia/Beijing  Sat Sep 14 15:00:00 1991 UT = Sat Sep 14 23:00:00 1991 CST isdst=0 gmtoff=28800

当初 GaussDB(DWS)中所有对于时区的常识都介绍完了,心愿从原理和保护角度的深刻学习彻底排除时区应用的纳闷,如果有相干问题欢送在论坛中发问。

5. 总结

综上,GaussDB(DWS)作为一款面向寰球用户的高性能剖析型数据库产品,对时区数据的反对也是合乎工业界标准规范的。

想理解 GuassDB(DWS)更多信息,欢送微信搜寻“GaussDB DWS”关注微信公众号,和您分享最新最全的 PB 级数仓黑科技~

点击关注,第一工夫理解华为云陈腐技术~

正文完
 0