标签:转变 方便 ima table 1.7 建议 中国 log summer
最近在学习关于时间、时区的知识,参考了网上的一些资料,主要来源是wiki和Linux Manual,现在把阅读过程中的一些心得记录下来。在本文中,简略描述了下列相关内容:
时间是一个很有趣的东西。远古人们基于太阳运转的昼夜交替,称之为日;观察月亮的盈缺变换,在两次月圆之间的周期定为月;再通过测量太阳南北周期变化,年的概念。
日月年,是最早出现的时间度量,也是历法的基本元素,其中又以日
最为基本。历法是人类社会指导耕牧采集的重要依据,为了完善历法,要求天文学不断进步以对时间做更精确的测量。所以,早期的时间观念,是天文学的产物。
一日
是很长的,生活中用起来还是不方便,还需要进一步细分。中华地区采取的是时辰
加刻
的记录方式,把一日划分为12个时辰,以12地支记录。1个时辰还是太长了,所以又出现了刻。一天的总刻数,出现过100、96、108、120等多种度量,直到清朝时最终确定为96刻,并恰好和西方的"Quarter"对应,1个时辰=8刻=2小时。 在后面的发展中,又对小时进行了细化,出现了分钟、秒,乃至毫秒和微秒等。
以上是一本正经的胡说八道。
前面说道的日月年、时分秒都是一个时段,要很好的表示时间,方便交流沟通,必须有一个完善的计时系统。计时系统最重要的就是参考点,最明显的一个参考点,就是正午。正午,也就是一天之中太阳位于最高点的时刻
。中国古代称之为午时
,英语称之为midday
,也就是一天的正中间。以正午为参考点,往前后各推12个小时,作为一天时间范围的度量。
这种基于本地太阳升落制定的时间度量,称为本地时, local time
。本地时很有用,它符合人类社会漫长发展过程中形成的时间观念,便于安排作息:在中国,辰时劳作,酉时归歇;在西方,9点上班,5点下班。
本地时对当地的意义重大,对其他地区可能就毫无意义。地球是圆的,不同地区正午到达时刻相差可以很大。以上帝视角观察地球,会发现:你在正午的时候,我可能还要过2个小时才到正午,他可能是2个小时前刚刚过了正午。所以单纯的正午
这个词没有任何意义,还必须说明:xxx地区的正午
。
早期受限于活动范围和运动速度,本地时的特点并不会对实际生活产生影响。18世纪随着铁路运输的发展,人类开始有能力长途快速旅行的时候,确立一个合理的计时方法就很有必要,这样才能指定沿铁路线统一的列车时刻表。
最直观的方法,就是选取某个地区的本地时间作为标准时间(uniform standard time),大家都用它。比如新中国就统一使用北京时间作为参考。
标准时间最大的作用:确立了一个起点
,可以计算当前时刻距离该起点
过去了多长时间段
。时间是单调流逝的,从起点开始算起,流逝的天数总是不断增加,各地都完全一致。
十九世纪,全球大规模交流发展起来之前,特别是电信系统诞生之前,远距离瞬时通信能力缺乏,一些比较强大的国家大都有一套自己的计时系统独立运作。其中一些国家的计时系统随着国力增强,全球影响力增加,逐步输出到世界其他地域,并最终成为全球范围的标准计时系统,
英国选取了格林威治天文台的一条子午线作为基点,以格林威治区域平均太阳时作为航海运输的参照标准,这就是Greenwich Mean Time(GMT)
。在天文台,有一个实实在在的时钟在运转,如下图。
1884年的Washington Meridian Conference上,GMT被选取作为国际计时标准。全球划分为24个时区
,每个时区都以中心点的平均太阳时作为标准时钟时间(wall-clock time),相邻时区的时钟时间相差1小时。
时区的作用:根据参考原点和当前时区,调整
挂钟时间
的显示。参考原点的时间是单调递增的,但某个具体地点的时区可以人为规定,挂钟时间
也可人为调整。
1935年,国际天文联会建议使用Universal Time 替代Greenwich Mean Time,因为后者有多个版本:GMT民用时,从午夜开始作为0点,GMT天文时,从正午开始作为0点。
1955年,国际天文联会基于Universal Time又定义了UT1和UT2三个系统,以消除极移和自转速率季节性变化的影响,原来的UT系统被称为UT0。
它们之间的关系可以表示为:
目前应用最广泛的是UT1。UTx的基本单位是天,1天等分为24小时,每小时等分为60分,1分钟等分为60秒。所以,UTx里面的秒
,并不是基本单位。
UTx系统1天=24小时=86400秒
1955年,铯原子钟问世。
1958年,制订了一套新的基于原子钟的计时系统: International Atomic Time system, 国际原子时系统。它以 "1958-01-01 00:00:00" 做为起始点和 UT2 同步,能提供非常精确的计时服务。
TAI的计时基元是秒,每天固定86400秒
,这里的秒是物理学定义的国际单位制SI second
:
铯133原子基态的两个超精细能阶间跃迁对应辐射的9,192,631,770个周期的持续时间
1960年,Coordinated Universal Time 被国际电信联会提出。
1972年,引入闰秒机制,形成了当前使用的UTC体系。简单的说,UTC是以TAI为基础的一种计时体系,它的计时单位是TAI second
,但时刻上又和UT1接近,不会超过1秒的差异,可以理解为Universal Time base on TAI, Coordinated with UT1
。这是当前普遍使用的计时系统。
UT0/UT1/UT2和UTC的比较:
天
。时分秒是对天的切分。TAI second
(base on TAI)与此对应,UT的秒
是太阳日的1/86400
,二者并不完全一致。所以,当TAI按照精确步调往前走的时候,UT1随着地球的自转变慢在逐渐减速,到目前为止,TAI已经领先了37秒左右。
UTC和UT1同步,某一天可能会增加1 TAI second
,这就是闰秒(Leap second)。下面是TAI1999年时,给UTC增加1闰秒的例子,此时最后1分钟有61秒而不是60秒。
TAI (1999-01-01) | UTC (1998-12-31到 1999-01-01) |
1999-01-01T00:00:29.75 | 1998-12-31T23:59:58.75 |
1999-01-01T00:00:30.00 | 1998-12-31T23:59:59.00 |
1999-01-01T00:00:30.25 | 1998-12-31T23:59:59.25 |
1999-01-01T00:00:30.50 | 1998-12-31T23:59:59.50 |
1999-01-01T00:00:30.75 | 1998-12-31T23:59:59.75 |
1999-01-01T00:00:31.00 | 1998-12-31T23:59:60.00 |
1999-01-01T00:00:31.25 | 1998-12-31T23:59:60.25 |
1999-01-01T00:00:31.50 | 1998-12-31T23:59:60.50 |
1999-01-01T00:00:31.75 | 1998-12-31T23:59:60.75 |
1999-01-01T00:00:32.00 | 1999-01-01T00:00:00.00 |
1999-01-01T00:00:32.25 | 1999-01-01T00:00:00.25 |
1999-01-01T00:00:32.50 | 1999-01-01T00:00:00.50 |
1999-01-01T00:00:32.75 | 1999-01-01T00:00:00.75 |
1999-01-01T00:00:33.00 | 1999-01-01T00:00:01.00 |
1999-01-01T00:00:33.25 | 1999-01-01T00:00:01.25 |
年份 | 计时系统 | 基本单位 | 注释 |
1884 | GMT | 太阳日 | 1天=24小时=1440分=86400秒 |
1955 | UT1 | 太阳日 | 1天=24小时=1440分=86400秒 |
1958 | TAI | SI second | 1天=86400 SI seconds |
1972 | UTC | SI second | 平时 1天=86400 SI seconds, 闰秒发生时 1天=86401 SI seconds |
Unix time是一个计时体系,度量从 UTC 时间 "1970-01-01 00:00:00 +0000" 开始流逝的秒数。但是,Unix time的数值不包含闰秒,所以它既不是对时间的线性度量,也不是UTC的一种合法表示。date +%s
可以查看Unix-like系统的当前Unix time。
因为Unix time是基于Unix epoch("1970-01-01 00:00:00 +0000"),所以又称为"epoch time"。
Unix Time一般表示为有符号十进制数值, "1970-01-01 00:00:00 +0000"之前的时刻,是负值,例如:
$ ./utc_time "UTC+0" -86400
-86400 1969-12-31 00:00:00 +0000
Unix time不包括闰秒,而UTC是有闰秒的,所以闰秒发生的时候,Unix time会发生数值回退
现象。下面是1999年插入闰秒时的情形:
TAI (1 January 1999) | UTC (31 December 1998 to 1 January 1999) |
Unix time |
1999-01-01T00:00:29.75 | 1998-12-31T23:59:58.75 | 915 148 798.75 |
1999-01-01T00:00:30.00 | 1998-12-31T23:59:59.00 | 915 148 799.00 |
1999-01-01T00:00:30.25 | 1998-12-31T23:59:59.25 | 915 148 799.25 |
1999-01-01T00:00:30.50 | 1998-12-31T23:59:59.50 | 915 148 799.50 |
1999-01-01T00:00:30.75 | 1998-12-31T23:59:59.75 | 915 148 799.75 |
1999-01-01T00:00:31.00 | 1998-12-31T23:59:60.00 | 915 148 800.00 |
1999-01-01T00:00:31.25 | 1998-12-31T23:59:60.25 | 915 148 800.25 |
1999-01-01T00:00:31.50 | 1998-12-31T23:59:60.50 | 915 148 800.50 |
1999-01-01T00:00:31.75 | 1998-12-31T23:59:60.75 | 915 148 800.75 |
1999-01-01T00:00:32.00 | 1999-01-01T00:00:00.00 | 915 148 800.00 |
1999-01-01T00:00:32.25 | 1999-01-01T00:00:00.25 | 915 148 800.25 |
1999-01-01T00:00:32.50 | 1999-01-01T00:00:00.50 | 915 148 800.50 |
1999-01-01T00:00:32.75 | 1999-01-01T00:00:00.75 | 915 148 800.75 |
1999-01-01T00:00:33.00 | 1999-01-01T00:00:01.00 | 915 148 801.00 |
1999-01-01T00:00:33.25 | 1999-01-01T00:00:01.25 | 915 148 801.25 |
time()函数返回的是整数部分,观察不到小数部分的回退。
Linux 以TZ环境变量设定当前时区,通过在C/C++里面,通过setenv就可以设置,例如:
setenv("TZ", "EST+5EDT,M3.2.0/2,M11.1.0/2", 1);
TZ可以识别3种格式,前两种都是直接指定时区信息,最后一种是基于时区数据库。
std offset
参数列表:
[+|-]hh[:mm[:ss]]
。它的符号是当前时区的符号相反: 下面是几个合法的时区字符串
std offset1 dst [offset2],start[/time],end[/time]
参数列表:
Mm.w.d
,第m个月的第w周的第d天。 下面是一些合法的夏令时串:
1. `EST+5EDT,M3.2.0/2,M11.1.0/2`
美国纽约时间,从每年3月份的第2个周日开始,到当年11月份的第1个周日,从凌晨2点开始变更
2. `WGT3WGST,M3.5.0/-2,M10.5.0/-1`
:characters
characters是本地文件路径,例如 :
setenv("TZ", ":/usr/share/zoneinfo/US/Eastern", 1);
夏时制,另译夏令时间(英语:Summer time),又称日光节约时制、日光节约时间(英语:Daylight saving time),是一种为节约能源而 人为规定地方时间 的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮较早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。
美国国会2005年通过的能源法案,自2007年起,夏时制开始日期为3月的第二个星期日,结束日期为11月的第一个星期日。美国夏时制实行与否,完全由各州各郡自己决定。
下面演示一个进入和退出夏时制的例子。
美国纽约时间2016年夏令时起止点
2016-03-13 01:59:59 (+1s) 开始 1457852399/1457852400 2016-11-06 01:59:59 (+1s) 结束 1478411999/1478412000
$ ./utc_time :/usr/share/zoneinfo/US/Eastern 1457852399 1457852399 2016-03-13 01:59:59 -0500
$ ./utc_time :/usr/share/zoneinfo/US/Eastern 1457852400 1457852400 2016-03-13 03:00:00 -0400
$ ./utc_time :/usr/share/zoneinfo/US/Eastern 1478411999 1478411999 2016-11-06 01:59:59 -0400
$ ./utc_time :/usr/share/zoneinfo/US/Eastern 1478412000 1478412000 2016-11-06 01:00:00 -0500 注意,如果这是一个普通挂钟的话,指向凌晨2点时,要把时针回拨1个小时。
代码片段:
setenv("TZ", argv[1], 1); time_t tt = (time_t)strtoll(argv[2], 0, 0); struct tm *ptm = localtime(&tt); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z", ptm);
标签:转变 方便 ima table 1.7 建议 中国 log summer
原文地址:http://www.cnblogs.com/skylerjiang/p/6344204.html