一、 说明及关系(GMT,UTC,DST,CST,CET)

1. 说明

  • GMT:「格林威治标准时间」(Greenwich Mean Time,简称G.M.T.)
  • UTC: Coordinated Universal Time- 世界协调时间(又称世界标准时间、世界统一时间),
  • DST:夏日节约时间」Daylight Saving Time(简称D.S.T.),
  • CST:4个不同的时区:
    • Central Standard Time (USA) UT-6:00
    • Central Standard Time (Australia) UT+9:30
    • China Standard Time UT+8:00
    • Cuba Standard Time UT-4:00
    • CST可以同时表示美国,澳大利亚,中国,古巴四个国家的标准时间。
  • CET:Central European Time,CET)欧洲中部时间

2. 时间和时区的关系

  • UTC=GMT
  • CET=UTC/GMT + 1小时
  • CST=UTC/GMT +8 小时
  • CST=CET+7

全球24个时区的划分

相较于两地时间表,可以显示世界各时区时间和地名的世界时区表(World Time),就显得精密与复杂多了,通常世界时区表的表盘上会标示着全球24个时区的城市名称,但究竟这24个时区是如何产生的?过去世界各地原本各自订定当地时间,但随着交通和电讯的发达,各地交流日益频繁,不同的地方时间,造成许多困扰,于是在西元1884年的国际会议上制定了全球性的标准时,明定以英国伦敦格林威治这个地方为零度经线的起点(亦称为本初子午线),并以地球由西向东每24小时自转一周360°,订定每隔经度15°,时差1小时。而每15°的经线则称为该时区的中央经线,将全球划分为24个时区,其中包含23个整时区及180°经线左右两侧的2个半时区。就全球的时间来看,东经的时间比西经要早,也就是如果格林威治时间是中午12时,则中央经线15°E的时区为下午1时,中央经线30°E时区的时间为下午2时;反之,中央经线15°W的时区时间为上午11时,中央经线30°W时区的时间为上午10时。以台湾为例,台湾位于东经121°,换算后与格林威治就有8小时的时差。如果两人同时从格林威治的0°各往东、西方前进,当他们在经线180°时,就会相差24小时,所以经线180°被定为国际换日线,由西向东通过此线时日期要减去一日,反之,若由东向西则要增加一日。

二、缩写详细说明

UTC

Universal Time Coordinated 协调世界时,又称世界标准时间。

多数的两地时间表都以GMT来表示,但也有些两地时间表上看不到GMT字样,出现的反而是UTC这3个英文字母,究竟何谓UTC?事实上,UTC指的是Coordinated Universal Time- 世界协调时间(又称世界标准时间、世界统一时间),是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间,计算过程相当严谨精密,因此若以「世界标准时间」的角度来说,UTC比GMT来得更加精准。其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务中央局发布闰秒,使UTC与地球自转周期一致。所以基本上UTC的本质强调的是比GMT更为精确的世界时间标准,不过对于现行表款来说,GMT与UTC的功能与精确度是没有差别的。

GMT

Greenwich Mean Time 格林尼治平均时。
UTC和GMT都与英国伦敦的本地时相同,所以程序中UTC与GMT没什么不同。意思UTC=GMT是相等的。

十七世纪,格林威治皇家天文台为了海上霸权的扩张计画而进行天体观测。1675年旧皇家观测所(Old Royal Observatory) 正式成立,到了1884年决定以通过格林威治的子午线作为划分地球东西两半球的经度零度。观测所门口墙上有一个标志24小时的时钟,显示当下的时间,对全球而言,这里所设定的时间是世界时间参考点,全球都以格林威治的时间作为标准来设定时间,这就是我们耳熟能详的「格林威治标准时间」(Greenwich Mean Time,简称G.M.T.)的由来,标示在手表上,则代表此表具有两地时间功能,也就是同时可以显示原居地和另一个国度的时间。

Unix时间戳

在计算机中看到的UTC时间都是从(1970年01月01日 0:00:00)开始计算秒数的。所看到的UTC时间那就是从1970年这个时间点起到具体时间共有多少秒。 这个秒数就是Unix时间戳。

CST时间

CST同时可以代表如下 4 个不同的时区:

  • Central Standard Time (USA) UT-6:00
  • Central Standard Time (Australia) UT+9:30
  • China Standard Time UT+8:00
  • Cuba Standard Time UT-4:00

CET

Central European Time 欧洲中部时间是比世界标准时间(UTC)早一个小时的时区名称之一。它被大部分欧洲国家和部分北非国家采用。冬季时间为UTC+1,夏季欧洲夏令时为UTC+2。

DST

Daylight Saving Time「夏日节约时间」

是指在夏天太阳升起的比较早时,将时钟拨快一小时,以提早日光的使用,在英国则称为夏令时间(Summer Time)。这个构想于1784年由美国班杰明·富兰克林提出来,1915年德国成为第一个正式实施夏令日光节约时间的国家,以削减灯光照明和耗电开支。自此以后,全球以欧洲和北美为主的约70个国家都引用这个做法。目前被划分成两个时区的印度也正在商讨是否全国该统一实行夏令日光节约时间。欧洲手机上也有很多GSM系统的基地台,除了会传送当地时间外也包括夏令日光节约时间,做为手机的时间标准,使用者可以自行决定要开启或关闭。值得注意的是,某些国家有实施「夏日节约时间」的制度,出国时别忘了跟随当地习惯在表上调整一下,这可是机械表没有的功能设计哦!

三、CST(中国沿海时间)与UTC(世界协调时间)之间的转换(C语言版)

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#if 0
typedef long __kernel_suseconds_t;
typedef __kernel_suseconds_t suseconds_t;
 
typedef struct timeval {
        time_t tv_sec; /* seconds */
        suseconds_t tv_usec; /* microseconds */
}TIMEVAL;
 
typedef struct timespec {
        time_t tv_sec; /* seconds */
        long tv_nsec; /* nanoseconds */
}TIMESPEC;
 
typedef struct timezone {
        int tz_minuteswest; /* minutes west of Greenwich */
        int tz_dsttime; /* type of dst correction */
}TIMEZONE;
#endif
/*
 *  * * The struct used to pass data via the following ioctl. Similar to the
 *   * * struct tm in <time.h>, but it needs to be here so that the kernel 
 *    * * source is self contained, allowing cross-compiles, etc. etc.
 *     * */
 
typedef struct rtc_time {
        int tm_sec;
        int tm_min;
        int tm_hour;
        int tm_mday;
        int tm_mon;
        int tm_year;
        int tm_wday;
        int tm_yday;
        int tm_isdst;
}RTC_TIME;
 
static const unsigned char rtc_days_in_month[] = {
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
 
static const unsigned short rtc_ydays[2][13] = {
        /* Normal years */
        { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
        /* Leap years */
        { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
 
#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400))
 
/*
 *  * The number of days in the month.
 *   */
int rtc_month_days(unsigned int month, unsigned int year)
{
        return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1);
}
 
/*
 *  * The number of days since January 1. (0 to 365)
 *   */
int rtc_year_days(unsigned int day, unsigned int month, unsigned int year)
{
        return rtc_ydays[LEAP_YEAR(year)][month] + day-1;
}
 
/*
 *  * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
 *   */
void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
{
        register int days, month, year;
 
        days = time / 86400;
        time -= days * 86400;
 
        /* day of the week, 1970-01-01 was a Thursday */
        tm->tm_wday = (days + 4) % 7;
 
        year = 1970 + days / 365;
        days -= (year - 1970) * 365
                + LEAPS_THRU_END_OF(year - 1)
                - LEAPS_THRU_END_OF(1970 - 1);
        if (days < 0) {
                year -= 1;
                days += 365 + LEAP_YEAR(year);
        }
        tm->tm_year = year - 1900;
        tm->tm_yday = days + 1;
 
        for (month = 0; month < 11; month++) {
                int newdays;
 
                newdays = days - rtc_month_days(month, year);
                if (newdays < 0)
                        break;
                days = newdays;
        }
        tm->tm_mon = month;
        tm->tm_mday = days + 1;
 
        tm->tm_hour = time / 3600;
        time -= tm->tm_hour * 3600;
        tm->tm_min = time / 60;
        tm->tm_sec = time - tm->tm_min * 60;
}
 
int main(void){
 
        struct timeval tv;
        struct timezone tz;
        RTC_TIME tm;
        gettimeofday(&tv, &tz);
 
        rtc_time_to_tm(tv.tv_sec, &tm);
        fprintf(stdout, "UTC time :%04d-%02d-%02d %02d:%02d:%02d \n", 
                        tm.tm_year+1900,tm.tm_mon, tm.tm_mday, tm.tm_hour, 
                        tm.tm_min, tm.tm_sec);
 
        rtc_time_to_tm(tv.tv_sec + 60*60*8, &tm);
        fprintf(stdout, "After adjust :%04d-%02d-%02d %02d:%02d:%02d \n", 
                        tm.tm_year+1900,tm.tm_mon, tm.tm_mday, tm.tm_hour, 
                        tm.tm_min, tm.tm_sec);
 
        return 0;
 

执行结果:

$ ./utc_cst_time 
UTC time :2019-04-28 13:44:57 
After adjust :2019-04-28 21:44:57