一些关于时间的笔记:
- UTC:处于零经度(亦最高经度)的国际标准时间。UTC是人为划分的。
- GMT:UTC过去被称为格林尼治标准时间(GMT),因为本初子午线通过格林威治皇家天文台。
- 其他时区都是在UTC时间的偏移。同一天里,UTC时间10:00是美国西海岸时间的20:00.
- 夏令时不影响UTC时间。夏令时仅仅是各国政府根据本国需要对时间的调整。比如英国在冬天使用GMT时间,而夏天使用英国夏令时时间(BST)。
- 闰秒:根据国际惯例,UTC通过保持小于物理时间0.9秒的误差。
- 在闰秒发生的六个月之前,预告闰秒不是必须的。如果你的计划周期超过六个月且需要秒级的时间精度,这就会导致问题。
- Unix时间:从1970年UTC时间开始的秒数。时区和夏令时不会对Unix时间造成影响。
- 根据POSIX.1标准,Unix时间被认为是可以通过重复秒数来处理闰秒。如下图:
59.00
59.25
59.50
59.75
59.00 ← replay 0.25秒后,时间从59.75进位到59.00秒
59.25
59.50
59.75
00.00 ← increment
00.25
这是一个折衷:你不能确切的描述一个闰秒,因为你的时间一定不可能会倒流。在另一方面,每一天都只有86400秒,你不需要包含所有以前和未来闰秒的表格以规范Unix时间,使之格式化为人类偏爱的:小时-分 - 秒。
- 另外请参阅:我的关于2012闰秒的文章 ,其中包含从一些系统获得的日志文件。日志显示了与Google闰秒抹涂一样的秒重复行为。
- 可以用leapfile配置ntpd以预测将要到来的闰秒。大多数服务器节点安装都不为此麻烦,他们依赖主动的时间同步确保时间正确。
编程过程中的一些时间相关的事项:
- 时区是表现层的问题。
你绝大多数的代码不应该处理时区或本地时间,时间应该以Unix时间传递。
- Libc和编程语言的运行时有对应的代码去做时区转换和时间格式化。
- 当衡量内部时间的时候,使用一个单调递增的时钟。读clock_getting()页。
- 当以时间记录一个点的时候,使用Unix时间作为量度。Unix时间是基于UTC的,它是容易获取到的。而且它没有时区偏移、夏令时变换和闰秒的(从某种程度上说)。
- 当需要保存时间戳(timestamp)的时候,使用Unix时间,它只是一串简单的数字。
- 如果你想存储人类可以识别的时间(如日志),考虑把Unix时间和人类可识别的时间一并存储。
- 当显示时间的时候,总是包含时区偏移信息。没有偏移量的数据格式是无用的。
- 系统时钟是不准确的。
- 如果你连接了网络,其他人的系统时钟都是不准确的。
- 系统时钟能够而且可能会根据你不可控的因素来来回回的跳动(比如闰秒,时钟同步过程中时钟的调整)。你的程序需要设计的足够健壮以适应该种情况。
- 计算机内部的时钟与真实物理时钟相比,计算机时钟是不准确并且是可变的。因为大多数情况下,计算机时钟随温度变化。
- ntpd可以从以下两个方面改变系统时间:
阶梯方式:通过使计算机时钟逐增或逐减的方式同步到正确时间的方式。
注意:Unix系统时间同步是以毫秒(或几十秒)为单位逐步调整的,并且同步源与同步对象之间时间差不能超过15分钟。但Linux系统根据同步源时间,直接修改其系统时间为准确时间。
回旋方式:通过修改时钟频率使系统时钟逐减接近正确时间。因为回旋方式对系统扰动更小,所以更推荐使用该方法。但是它只能适用于非常小的时钟误差。
特别需要说明的:
- 对应任何一个观察者来说,时间是按照1s/second的速度进行的。但对一个观察者来说,远端时钟的频率是受速率和重力影响的。GPS卫星中的时钟会根据相关的影响因素适时调整。
- MySQL(至少4.x和5.x)会把DATETIME类型“YYYY-MM-DD HH:MM:SS”格式的字符串保存为二进制编码类型。由于没有保存时区偏移信息,其通过@@session.time_zone解释时间:
mysql> insert into timesvalues(now());
mysql> select unix_timestamp(t) from times;
1310128044
mysql> SET SESSION time_zone='+0:00';
mysql> select unix_timestamp(t) from times;
1310164044
MySQL中也有以Unix时间作为存储类型的TIMESTAMP。
总结:如果你对MySQL中timestamps时间的保存问题,那么把其保存为integers类型,并使用UNIX_TIMESTAMP() and FROM_UNIXTIME()函数。