7.2.4时间转换函数
通过 time()或 gettimeofday()函数可以获取到当前时间点相对于 1970-01-01 00:00:00 +0000 (UTC)这个时间点所经过时间(日历时间),所以获取得到的是一个时间段的长度,但是这并不利于我们查看当前时间。
本小节将向大家介绍一些系统调用或 C 库函数,通过这些 API 可以将 time()或 gettimeofday()函数获取到的秒数转换为利于查看和理解的形式。
ctime 函数
ctime()是一个 C 库函数,可以将日历时间转换为可打印输出的字符串形式。
#include <time.h>
char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);
/*函数参数如下:
timep:time_t 时间变量指针。
返回值:
成功将返回一个 char *类型指针,指向转换后得到的字符串;
失败将返回 NULL。*/
只需将 time_t 时间变量的指针传入即可,调用成功便可返回字符串指针,拿到字符串指针之后,可以使用 printf 将其打印输出。
但是 ctime()是一个不可重入函数,存在一些安全上面的隐患。
ctime_r()是 ctime()的可重入版本,一般推荐大家使用可重入函数 ctime_r()。
可重入函数 ctime_r()多了一个参数 buf,也就是缓冲区首地址,所以 ctime_r()函数需要调用者提供用于存放字符串的缓冲区。
ctime(或 ctime_r)转换得到的时间是计算机所在地对应的本地时间(譬如在中国对应的便是北京时间),并不是 UTC 时间。
localtime 函数
localtime()函数可以把 time()或 gettimeofday()得到的秒数(time_t 时间或日历时间)变成一个 struct tm结构体所表示的时间,该时间对应的是本地时间。
#include <time.h>
struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
/*函数参数:
timep:需要进行转换的 time_t 时间变量对应的指针,可通过 time()或 gettimeofday()获取得到。
result:是一个 struct tm 结构体类型指针,参数 result 是可重入函数
localtime_r()需要额外提供的参数。
返回值:
对于不可重入版本 localtime()来说,
成功则返回一个有效的 struct tm 结构体指针,
而对于可重入版本 localtime_r()来说,
成功执行情况下,返回值将会等于参数 result;
失败则返回 NULL。*/
不可重入函数 localtime()并不需要调用者提供 struct tm 变量,而是它会直接返回出来一个 struct tm结构体指针,然后直接通过该指针访问里边的成员变量即可!虽然很方便,但是存在一些安全隐患,所以一般不推荐使用不可重入版本。
可重入版本 localtime_r()调用者需要自己定义 struct tm 结构体变量、并将该变量指针赋值给参数result,在函数内部会对该结构体变量进行赋值操作。
struct tm 结构体如下所示:
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year; /* 年(这个值表示的是自 1900 年到现在经过的年数) */
int tm_wday; /* 星期(0-6, 星期日 Sunday = 0、星期一=1...) */
int tm_yday; /* 一年里的第几天(0-365, 1 Jan = 0) */
int tm_isdst; /* 夏令时 */
}
从 struct tm 结构体内容可知,该结构体中包含了年月日时分秒星期等信息,使用 localtime /localtime_r()便可以将 time_t 时间总秒数分解成了各个独立的时间信息。
gmtime 函数
gmtime()函数也可以把 time_t 时间变成一个 struct tm 结构体所表示的时间,与 localtime()所不同的是,gmtime()函数所得到的是 UTC 国际标准时间,并不是计算机的本地时间,这是它们之间的唯一区别。
mktime 函数
mktime()可以将使用 struct tm 结构体表示的分解时间转换为 time_t时间(日历时间) 。
#include <time.h>
time_t mktime(struct tm *tm);
/*函数参数:
tm:需要进行转换的 struct tm 结构体变量对应的指针。
返回值:
成功返回转换得到 time_t 时间值;
失败返回-1。*/
asctime 函数
asctime()函数与 ctime()函数的作用一样,也可将时间转换为可打印输出的字符串形式,与 ctime()函数的区别在于:
ctime()是将 time_t 时间转换为固定格式字符串、
asctime()则是将 struct tm 表示的分解时间转换为固定格式的字符串。
#include <time.h>
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
/*函数参数:
tm:需要进行转换的 struct tm 表示的时间。
buf:可重入版本函数 asctime_r 需要额外提供的参数 buf,指向一个缓冲区,
用于存放转换得到的字符串。
返回值:
转换失败将返回 NULL;
成功将返回一个 char *类型指针,指向转换后得到的时间字符串,
对于 asctime_r 函数来说,返回值就等于参数 buf。*/
strftime 函数
strftime()函数也可以将一个 struct tm 变量表示的分解时间转换为为格式化字符串,并且在功能上比 asctime()和 ctime()更加强大,它可以根据自己的喜好自定义时间的显示格式,而 asctime()和 ctime()转换得到的字符串时间格式的固定的。
strftime 函数的特殊格式说明符还是比较多的,不用去记它,需要用的时候再去查即可。
7.2.5 设置时间 settimeofday
使用 settimeofday()函数可以设置时间,也就是设置系统的本地时间。
#include <sys/time.h>
int settimeofday(const struct timeval *tv, const struct timezone *tz);
/*函数参数:
tv:参数 tv 是一个 struct timeval 结构体指针变量,struct timeval 结构体在前面章节内容中已经给大家介绍了,需要设置的时间便通过参数 tv 指向的 struct timeval 结构体变量传递进去。
tz:参数 tz 是个历史产物,早期实现用其来设置系统的时区信息,目前已遭废弃,在调用 settimeofday()
函数时应将参数 tz 设置为 NULL。
返回值:
成功返回 0;
失败将返回-1,并设置 errno。*/
使用 settimeofday 设置系统时间时内核会进行权限检查,只有超级用户(root)才可以设置系统时间,普通用户将无操作权限。
系统时间部分总结图。