几个关于时间的知识点
l UTC 在零度经线(本初子午线)上的时间叫做协调世界时(UTC)
l GMT UTC曾经叫做格林尼治标准时间(GMT),因为本初子午线通过了格林尼治天文台。
l 其他一些时区就是UTC的时间加上或减去一定的时间。例如,澳大利亚东部标准时间是 UTC+1000。在同一天的情况下,10:00UTC 就是20:00 EST (澳大利亚东部标准时间)。
l 夏令时和UTC没有关系,这只是一个用来改变本时区和UTC相差的时间的一个制度,例如,英国在冬天使用英国国家时区所在的时间,在夏天使用英国夏令时。
l 闰秒 按照国际惯例,为了保持UTC(人类一个随意的发明)和物理现实(UT1,一种计量太阳时间的方法)之间0.9以内的误差,通常在UTC年的最后一分钟或者六月的最后一分钟加上一秒。
l 没必要在闰秒出现之前声明它超过六个月(译者表示很费解),如果你有一个精确到秒而且持续时间超过六个月的计划任务话,这会是一个你不得不考虑的问题。
l UNIX时间 : 通过记录从UTC时间1970年1月1日到现在为止过了多少秒来描述时间,unix时间不受时区或者夏令时的影响
l 按照POSIX.1 ,UNIX时间通过重复前一秒来达到增加一闰秒的效果。例如:
59.00
59.25
59.50
59.75
59.00 ← 第59秒
59.25
59.50
59.75
00.00 ← 重复第59秒
00.25
这是一个折衷的办法,因为你不能表示一闰秒,保证时间倒退,另一方面,每一天都准确的86400秒,而且你不需要一个记录过去和未来闰秒的表格来格式化你的unix时间使其成为人能看懂的时:分:秒的格式。
l ntpd 会在它发现上游时间服务器有闰位(leap bits)的时候重新显示上一秒,但是我也见过ntpd在发现闰位(leap bits)的时候什么都不做,它继续显示下一秒,然后显示一秒的时间延长为两秒。
以下是每个程序员都应该知道的关于时间的知识:
l 时区是一个表示层问题
你的绝大部分程序都不应该去处理时区或者是本地时间问题,时间可以通过unix系统时间传送得到。
l 当你需要计量时间的时候,使用unix时间吧,它是UTC时间,不仅容易获得,而且没有时区时差,夏令时,闰秒的影响。
l 当你需要存储时间的时候,存储unix时间吧,这只是一个数字而已。
l 如果你想要存储一个人能够读懂的时间,考虑把它和unix时间一起存储,而不是仅存储人类可读的时间(时:分:秒格式,译者注)。
l 当你需要显示时间的时候,记住要包含时区的时差,一个时间表示在没有包含时差(与UTC的时差。译者注)的时候是没有意义的。
l 系统时钟是不准确的。
l 你联网了吗?每台其它计算机的系统时钟是不一样的。
l 系统时钟会由于某些你不能控制的原因往后或是往前跳转时间,你的程序应该避免受到此类问题的干扰。
l 时钟上每经过的一秒和真正的一秒的时间也是不准确而且易变的,通常伴随着温度的变化。
l 不要盲目的使用gettimeofday()函数,如果你需要一个单调(上升。译者注)的时间,请参考一下clock_gettime()。
l ntpd可以通过以下两种方法修改系统时间:
n 跳转:使时钟往前或往后瞬间跳转到正确的时间
n 调速:调整时钟的频率使得时钟慢慢调整到正确的时间
调速方法由于破坏性小一点的缘故使用得多一点,但是这个方法只能用来纠正误差范围比较小的时间偏差。
特别提醒:
l 时间流逝的速率相对于每一个独立的观察者而言是每秒逝去一秒钟,而远处的时钟频率相对于观察者来说受到速度和重力的影响,GPS卫星的内置时钟由于相对论的影响需要调整时间。
l MySQL(至少 4.X 和 5.X)存储DATETIME类型是通过存储格式串“YYYY-MM-DD HH:MM:SS”的二进制编码来实现的,并不保存时间的时差,下面通过@@session,time_zone来解释:
mysql> insert into times values(now());
mysql> select unix_timestamp(t) from times;
1310128044
mysql> SET SESSION time_zone='+0:00';
mysql> select unix_timestamp(t) from times;
1310164044
如果你关心所有存储时间戳的问题,用整型类型来存储它们而且用UNIX_TIMESTAMP()和FROM_UNIXTIME()函数。
也有TIMESTAMP 类型,这种类型以UNIX时间来存储,但是有其他的影响(原文为magic,译者注)。