UTC、GMT、CST、DST以及Unix时间戳

UTC - 时间标准时间

全球通用的时间标准,是一堆大佬根据原子钟和地球自转计算出来的。

GMT - 格林威治时间

规定太阳每天经过位于英国伦敦郊区的皇家格林威治天文台的时间为中午12点。

GMT是前世界标准时,UTC是现世界标准时。UTC以原子时计时所以比GMT更精确,但是日常生活中精确到秒的情况下,二者可以视为相同

CST - Central Standard Time

可同时代表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

DST - 夏令时

为了节约能源,提高日光利用率,夏季太阳升起较早人为将时间调快一个小时,夏令时切换当天一天只有23个小时,同时冬令时切换当天,一天有25个小时

Unix时间戳

UNIX时间戳是UTC时间,从1970年01月01日00时00分00秒到现在的总秒数,与时区无关。

Linux时间函数

精确到秒

struct tm{
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;
};

#include <time.h>
time_t time(time_t *timer); //返回unix时间戳,如果传参不为空,则返回值也报错在参数里,以秒为单位
time_t stime(time_t *timer); //设置系统时间
char *ctime(const time_t *timer); //将unix时间戳转换为字符串,格式: 星期 月 日 小时:分:秒 年
struct tm *localtime(const time_t *timer); //将unix时间戳填充到tm结构体中
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)//将tm结构体按照指定格式保存到str

精确到毫秒

#include <unistd.h>
#include <sys/time.h>
struct timeval{
long tv_sec; // 秒数
long tv_usec; // 微秒数
};

struct timezone{
int tz_minuteswest;//GMT往西方的小时数,一般配合tzset函数使用
int tz_dsttime;//夏令时
};
int gettimeofday(struct timeval *tv,struct timezone *tz); //获取时间和时区信息
int settimeofday(const struct timeval *tv, const struct timezone *tz); //设置时间和时区信息
/*
daylight:整数全局变量,用于表示当前时区是否遵循夏令时(Daylight Saving Time)。如果 daylight 的值为非零,则表示当前时区遵循夏令时规则,否则为零。
timezone:长整型全局变量,用于表示当前时区与 Coordinated Universal Time(UTC)之间的偏移量,单位为秒。它表示当前时区相对于 UTC 的时间差,包括夏令时调整。
tzname:字符数组,用于存储时区的标准名称和夏令时名称。通常 tzname[0] 存储标准时区名称,tzname[1] 存储夏令时时区名称。
*/
#include <time.h>
void tzset(void); //给daylight,timezone和tzname三个全局变量赋值。

设置时区

规定地理位置相对于GMT以西为+,以东为-,东八区:GMT-8。

TZ环境变量取值规则

参考该文章即可:

  • TZ取值规则
    当TZ取值为时区名时,对应的zoneinfo文件必须存在,如果zoneinfo不在默认路径,可以使用TZDIR环境变量配置

设置方法

  1. 通过设置环境变量
    export TZ=GMT-8
  2. 通过文件etc/TZ
    echo "Asia/Shanghai" > /etc/TZ
    注意:环境变量优先于文件
  3. 进程内部设置
    #include<stdlib.h>
    int setenv(const char *name, const char *value, int overwrite); //设置环境变量,仅对当前进程有效 setenv("TZ","GMT-8",1);
  4. zoneinfo

Linux系统中的时区信息存储在/etc/localtime文件中,该文件是一个符号链接,指向实际的时区文件。这些时区文件通常位于usr/share/zoneinfo目录下,每个时区对应一个文件,文件名以所在地区的缩写命名,如Asia/Shanghai表示美国纽约时区。
zoneinfo是linx系统中用于管理时区信息的数据库.它包含了世界上各个时区的详细信息,包括时区名称、夏令时规则等。当系统启动时,它会读取/etc/localtime文件来获取当前系统的时区设置,然后根据这个设置去Zoneinfo数据库中查找对应的时区信息。

Linux C设置时区

该方法仅对当前程序生效

#include <time.h>
#include <sys/time.h>

int mian()
{
struct timeval tv;
struct timezone tz;
char cmd[128] = {0};
gettimeofday(&tv,&tz);
setenv("TZDIR", "/system/usr/share/zoneinfo", 1);
setenv("TZ", "Asia/Shanghai", 1);
tzset();
tz.tz_minuteswest = 0;
tz.tz_dsttime = 0;
settimeofday(NULL,&tz);
tz.tz_minuteswest = timezone/60;
settimeofday(NULL,&tz);
return 0;
}