基本概念
UTC全称为 Coordinated Universal Time 世界协调时,是一个时间体系。GMT全称为Greenwich Mean Time格林尼治平太阳时间,可以指一个时区。
GMT的计算是基于地球自转,一个周期约为86,400.002秒,它随着地球自转周期的变化而变化。UTC基于SI标准的原子时间,一个周期为精确的86,400.00秒,由于潮汐力等因素,地球自转周期在慢慢变长,当差别到±0.9秒时,就把协调世界时向前拨1秒或向后拨1秒这样就和GMT时间(地球自转)相同了。
东八区表示为 UTC+8 全球通用,英联邦国家则更倾向于使用 GMT+8。因此,UTC更为标准,在科学和工程中换算时间也是用UTC系统。
Epoch 指 UTC 时间从 1970 一月一日 0 时 0 分 0秒 开始的一个整数值
基本类型
C 语言使用下面五个类型来表示时间,time_t 和 clock_t 通常是一个整形来实现这个类型
time_t // 表示从 Epoch 开始计算的时间
clock_t // 进程消耗处理器的时间
struct tm {
int tm_sec; /* seconds after the minute [0-60] */
int tm_min; /* minutes after the hour [0-59] */
int tm_hour; /* hours since midnight [0-23] */
int tm_mday; /* day of the month [1-31] */
int tm_mon; /* months since January [0-11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday [0-6] */
int tm_yday; /* days since January 1 [0-365] */
int tm_isdst; /* Daylight Savings Time flag */
long tm_gmtoff; /* offset from UTC in seconds */
char *tm_zone; /* timezone abbreviation */
}; // 来表示日期
struct timespec {
__darwin_time_t tv_sec;
long tv_nsec;
}; // 秒和纳秒 C11/MSVC
struct timeb {
time_t time; /* [XSI] Seconds since the Epoch */
unsigned short millitm; /* [XSI] Milliseconds since the Epoch */
short timezone; /* [XSI] Minutes west of CUT */
short dstflag; /* [XSI] non-zero if DST in effect */
}; // 获取毫秒
struct timeval {
__darwin_time_t tv_sec; /* seconds */
__darwin_suseconds_t tv_usec; /* and microseconds */
}; // 秒和微秒 UNIX 系统下
获取系统时间
#include <time.h>
int main() {
time_t current_t;
time(¤t_t);
}
time 也可以使用返回值,传入指针比较块,time 函数返回的是秒数不精确,通常用来获取日历时间转化为 tm 结构体。
#include <sys/timeb.h>
int main() {
struct timeb current_t;
ftime(¤t_t);
}
timeb 有用的字段就是 time 和 millitm
#include <time.h>
int main() {
struct timeval current_t;
gettimeofday(¤t_t, NULL);
}
timeval 和 gettimeofday 在 UNIX 系统下生效
#include <time.h>
int main() {
struct timespec currrnt_t;
timespec_get(&currrnt_t, TIME_UTC);
}
timespec 在 C11 和 windows 下使用
本地时间
#include <time.h>
int main() {
time_t current_time;
time(¤t_time);
struct tm * cal_t = localtime(¤t_time);
}
time_t current_time_1 = mktime(cal_t);
mktime 用来反过来解析 tm 结构体,mktime 不仅会将结构体进行转换,而且会进行属性检查,例如 70 秒会转化为 1 分 10 秒。
time 将 time_t 根据电脑所在的时区转化成,gmttime 时间根据 time_t 转化成零时区的时间。
格式化时间
time_t current_time;
time(¤t_time);
struct tm * cal_t = localtime(¤t_time);
asctime(cal_t);
ctime(¤t_time);
char current_time[20];
strftime(current_time, %Y-%m-%d %H %M %S, cal_t);
// 等价于
strftime(current_time, %Y %T, cal_t);
C 语言标准库不支持毫秒但是我们可以追加上去,因为毫秒只是数字罢了
解析时间
将 strftime 处理出来的字符串解析成 tm 结构体,strptime 并不是标准库的函数是 poix 对于 c 标准的扩展,需要定义 _XOPEN_SOURCE 宏来开启
struct tm * cal_t;
char * unparsed_string = strptime(time, "%F %T", &cal_t);
可以使用返回值来解析毫秒数,返回值返回的是没有解析的字符串,也可以使用 sscanf 来解析 2020-11-10 23:10:9 这样的字符串
struct tm * cal_t;
char *time = "2020-11-10 23:10:09";
sscanf(time, "%4d-%2d-%2d %2d:%2d:%2d", &cal_t.tm_year, ...); // 省略
sscanf()会将参数str 的字符串根据参数format(格式化字符串)来转换并格式化数据(格式化字符串请参考scanf()), 转换后的结果存于对应的变量中。
程序时间差
cloct_t start_time = clock();
// do something
cloct_t end_time = clock();
CLOCKS_PRE_SEC
clock 函数返回一个整数,CLOCKS_PRE_SEC 定义了每秒有多少时钟,那么使用 clock_t 除以 CLOCKS_PRE_SEC 就得到了秒数,最好在除之前加一个 1.0 转换成浮点数。
clock 更能反应程序运行时间,比 time 更准确,因为 cpu 会同时执行很多程序,会并行执行,time 只反应真实世界经历的时间。