Greenwich Mean Time 格林尼治标准时间。是位于伦敦郊区的皇家格林尼治天文台观测太阳横穿格林尼治子午线时的时间。天文观测的蓬勃发展,最开始还是以欧洲为中心,谁牛谁就定规则,所以不要问为嘛听伦敦皇家天文台的。
universal time 世界时。以本初子午线的平子夜起算的平太阳时。大致是这么个意思,平太阳是一美国天文学家假想的太阳,因为地球本身并不非常圆,自转又不均匀,而且总靠人去观测太阳的位置也挺麻烦的,要机器计时,就得建立一套理解系统,所以就假想了很多东西,包括一个匀速公转的太阳,就叫平太阳。这样的时间不是特别准,但是一年到头是很均匀运转,非常方便机械计时。
international atomic time 即国际原子时。我曾经非常困惑,标准质量单位KG,是由国际千克原器来指定的,最初的国际千克原器是4℃时1立方分米纯水的质量为1千克,后来变成铂铱合金(10%Ir加90%Pt)制成一个高度和直径都是39毫米的圆柱体为1千克,但是时间怎么指定呢,看不见摸不着的东西。后来才知道是这么规定的,铯原子在海平面,零磁场下,某两个相邻能级之间的跳跃时长规定为1秒。又取1958年1月1日0时0分0秒世界时的瞬间作为原子时的开始。这就是国际原子时,非常精准。
Coordinated Universal Time 协调世界时。是原子时对世界时的协调折中,毕竟原子时是人为定义的,而世界时是根据太阳和地球公转与自转抽象出来的,两者之间是有微小差距的,于是就出了个折衷时间。由此,就出现了一种现象,过个几年,一些国际组织站出来说,我们要闰一秒,或者闰负一秒的情况,这就是协调与折中的表现。协调世界时被认为世界标准时间,然后各国时间再按时区计算得到,比如中国就是UTC + 8小时,因为北京是东八区。
Daylight Saving Time 夏令时,是各个国家为使人们早起早睡,减少因照明带来的能源浪费,强制调快时间。中国不大需要这个,因为北京本来就处在中国东部,而全国都统一使用北京时间,相当于中国的中西部地区时间被调早了,而莫斯科在俄罗斯的西部,他们就喜欢搞夏令时。
Central Daylight Time 的缩写,即,美国中部夏令时间(或美国中部夏季时间)。
常见的时区缩写为:
缩写 | 时间 | 含义 |
---|---|---|
CCT | +8:00 | 中国沿海时间(北京时间) |
EDT | -4:00 | (美国)东部夏令时 |
CDT | -5:00 | (美国)中部夏令时 |
EST | -5:00 | (美国)东部标准时间 |
CST | -6:00 | (美国)中部标准时间 |
MDT | -6:00 | (美国)山地夏令时 |
MST | -7:00 | (美国)山地标准时间 |
PDT | -7:00 | (美国)太平洋夏令时 |
PST | -8:00 | (美国)太平洋标准时间 |
注意:上表中的CST正好也是china standard time的缩写,所以有时候CST是指中国标准时间,而不是指美国的。
Linux上的时间函数在这篇文章Linux上的各种时间函数里有罗列。我不赞成在C代码里设置时区, 因为查询时区是个很消耗性能的事情,像一些开源软件,比如Nginx里,日志里打印的时间都是这么写的12:23:45 +8:00
, 即将时区以小时差值的形式写出来,也提高了性能。但如果不考虑性能,如何在C代码里指定时区呢?
mktime、localtime之类的函数都会用到时区,这时就需要指定时区环境变量TZ,设置TZ时有三种格式。
setenv("TZ", ":Asia/Shanghai", 1);
指定时区文件名,上面就是指定时区文件/usr/share/zoneinfo/Asia/Shanghai
,所以有多少种时区,对应什么城市,可以在/usr/share/zoneinfo/
下找找。
setenv("TZ", "CCT-8:00", 1);
CCT
表示时区代号,-8:00
表示时区差值,我想这种方式,可能不会有太大的性能消耗,因为不用去查找文件嘛。
setenv("TZ", "NZST-12:00:00NZDT-13:00:00,M10.1.0,M3.3.0", 1);
格式三不大常用,是专为设置夏令时提供的,NZST-12:00:00
跟格式二相似,就是设置一名字,以及相应的时差,这个例子中是New Zealand standard time,NZDT-13:00:00
是夏令时名字和时差,英文是New Zealand daylight saving time,M10.1.0,M3.3.0
表示夏令时的开始时间和结束时间,可见夏令时通常只是持续一段时间而已,也有像俄罗斯那样,永久提前的。
举个代码例子:
int main()
{
setenv("TZ", "CCT-8:00", 1);
const char * date = "2014-01-16";
struct tm my_tm;
struct tm my_tm2;
memset(&my_tm, 0, sizeof(my_tm));
memset(&my_tm2, 0, sizeof(my_tm2));
strptime(date, "%Y-%m-%d", &my_tm);
strptime(date, "%Y-%m-%d", &my_tm2);
time_t t = timegm(&my_tm) - 8 * 3600;
printf("timegm=%lu\n", t);
t = mktime(&my_tm2);
printf("time =%lu\n", t);
//timelocal == mktime
t = timelocal(&my_tm2);
printf("timelocal = %lu\n", t);
printf("%s\n", tzname[0]);
printf("%s\n", tzname[1]);
return 0;
}