【C/C++】日常时间的获取、格式化等操作汇总
文章结构如下:
C支持的日常时间种类
C支持的日常时间格式或种类有这三种:
#####1.时间值`time_t
时间值是指从1970-01-01 00:00:00 +0000 (UTC) 这个时间点开始到当前时间的秒数。
在C语言中,用time_t
来表示一个秒数,查看头文件可以发现time_t
是对long
的一个重定义而已。
相关函数time()
。
#####2.时间详情 `struct tm
有了具体的时间值time_t
,但存在着阅读和理解不方便的问题,所以希望可以把时间值转化为相应的年、月、日、时、分、秒等数据。
对应的结构体为struct tm
。如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
struct tm {
int tm_sec; /* 秒,取值范围(0~59),但当遇到闰秒时则会有60秒的取值。 */
int tm_min; /* 分钟数,取值范围(0-59) */
int tm_hour; /* 小时数,取值范围(0-23) */
int tm_mday; /* 当天在这个月中是第几天,取值范围(1-31) */
int tm_mon; /* 当前月份是第几个月,取值范围(0-11) */
int tm_year; /* 从1900年开始至今的年数,即(Year - 1900)的值 */
int tm_wday; /* 当天在本周是第几天,取值范围(0-6, Sunday = 0) */
int tm_yday; /* 当天在今年是第几天,取值范围(0-365, 1 Jan = 0) */
int tm_isdst; /* 夏令时标记,值大于0表示夏令时生效;等于0表示夏令时失效;小于0表示数据不可用。 */
char *tm_zone; /* 时区名称,根据系统不同可能不被声明或不同全名。 */
};
相关函数 localtime()
gmtime()
。
#####3.时间字符串 (char *)
有了年、月、日等具体的数据,C也提供函数将数据转为转为可视的、有意义的字符串。
相关函数
- 固定格式时间文本:
ctime()
asctime()
- 自定义格式时间文本:
strftime()
。
日常时间函数的调用关系
由于涉及到日常时间的函数比较多,这里整理了一张它们的关系图如下:
好了,先看一眼就好。下面来逐一讲解图中的函数。
日常时间函数的讲解
首先,日常时间函数都需要#include <time.h>
。
获取当前时间值
time_t time(time_t *t);
time_t mktime(struct tm *tm);time()
可以从当前系统中获取时间值并返回,如果参数t
不为NULL,则时间值同样也会存储中t
中。
如果函数执行异常,则返回-1,可通过errno
查询出错原因。mktime()
则是将struct tm
逆解析为time_t
的函数。
如果参数tm
是由用户自己组装的,则tm
中的tm_wday
和tm_yday
会在本函数执行后根据tm
中的tm_year``tm_mon
…等字段计算为真实的值。
获取时间详情
时间详情也就是上文所说的struct tm
,manual中也把struct tm
称为broken-down time。相关函数:
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);
struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
gmtime()
和localtime()
都可以把时间值转换为时间详情,两者的区别在于gmtime()
所得到的结果是世界标准时间Coordinated Universal Time (UTC)
;而localtime()
获取的是本地时间。以北京时间为例,gmtime()
得到的结果比localtime()
要提前(早)8小时。
gmtime_r()
和localtime_r()
分别是gmtime()
及localtime()
的可重入实现版本。
当函数执行错误时,则返回NULL,可通过errno
查询出错原因。
格式化的时间字符串
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);
asctime()
能直接从时间详情中计算出时间字符串,该字符串包含字符串终止符,计算出来的时间字符串格式是固定的,示例为:Wed Jun 30 21:49:08 1993\n
。ctime()
则是asctime(localtime(time_t))
的封装实现。
asctime_r()
和ctime_r()
分别是asctime()
及ctime()
的可重入实现版本。
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
C语言为了格式化输出时间信息又提供了强大的格式化函数strftime()
,支持按自定义的格式打印出完整可阅读的时间信息,包括月份的全称或简称,或只选择某些关键时间值进行输出。
参数s
指向格式化后的时间字符串。
参数max
表示时间字符串的最大字符数(含字符串终止符)。
参数format
表示时间字符串的格式化表达式。
参数tm
表示待格式化的时间详情。
其中format
表达式支持格式化参数与字符混合使用,且所支持的格式化参数非常多,具体可以查阅manual。
下面仅挑几个常用的来说:
格式化参数 | 含义 |
---|---|
%Y | 完整的年数字 |
%m | 月份,如月份是1~9,则数字前填充一个’0’。 |
%d | 日子 |
%F | 等同于“%Y-%m-%d” |
%H | 小时数 |
%M | 分钟数 |
%S | 秒数 |
%_m | 月份,如果月份是1~9,则数字前有一个空格填充。 |
%-m | 月份,如果月份是1~9,仍只显示该数字。 |
示例代码
在这里要多提及一个时间计算函数:
double difftime(time_t time1, time_t time0);
用于计算time1
与time0
之间的时间差,并转换为double
,即结果为秒数。
下面是以上提及的所有函数的示例代码:
1 | // author:sodino@qq.com |
执行效果: