C语言 time.h 头文件详解
- 一、头文件详解
- 1. 引言
- 2. 核心类型
- 2.1 `time_t`
- 2.2 `struct tm`
- 2.3 `clock_t`
- 3. 常用函数
- 3.1 `time()` — 获取当前时间
- 3.2 `localtime()` 与 `gmtime()` — 时间转换
- 3.3 `strftime()` — 格式化时间输出
- 3.4 `mktime()` — 将 `struct tm` 转回 `time_t`
- 3.5 `difftime()` — 计算时间差
- 3.6 `clock()` — 测量处理器时间
- 3.7 `asctime()` 与 `ctime()` — 简单字符串输出
- 4. 综合示例:完整的日期时间工具
- 5. 注意事项
- 6. 总结
- 二、代码示例
一、头文件详解
1. 引言
在 C 语言的标准库中,<time.h>头文件提供了处理日期和时间的函数与类型。无论是记录程序运行耗时、生成时间戳,还是格式化输出当前时间,<time.h>都是开发者不可或缺的工具。本文将系统讲解<time.h>中的核心类型、常用函数以及实际应用示例,帮助你彻底掌握 C 语言中的时间处理。
2. 核心类型
<time.h>中定义了若干与时间相关的数据类型,理解它们是使用时间函数的前提。
2.1time_t
time_t是一个算术类型(通常是long或long long),用于表示从 1970 年 1 月 1 日 00:00:00 UTC(Unix 纪元)起经过的秒数。它是最基础的时间表示形式。
#include<time.h>time_tnow;now=time(NULL);// 获取当前时间(秒数)2.2struct tm
struct tm是一个结构体,将时间拆分为年、月、日、时、分、秒等可读字段,便于程序直接访问。
structtm{inttm_sec;// 秒(0-59)inttm_min;// 分(0-59)inttm_hour;// 时(0-23)inttm_mday;// 日(1-31)inttm_mon;// 月(0-11,0 表示一月)inttm_year;// 年(自 1900 起的年数)inttm_wday;// 星期(0-6,0 表示星期日)inttm_yday;// 一年中的第几天(0-365)inttm_isdst;// 夏令时标志};注意:tm_mon从 0 开始,tm_year从 1900 开始,使用时需要相应调整。
2.3clock_t
clock_t用于表示处理器时钟计时单元(clock ticks),通常配合clock()函数测量程序运行时间。
3. 常用函数
3.1time()— 获取当前时间
time_ttime(time_t*timer);返回当前日历时间(秒数)。若timer不为NULL,也会将结果写入该指针指向的变量。
time_tnow=time(NULL);printf("当前时间戳:%ld\n",(long)now);3.2localtime()与gmtime()— 时间转换
structtm*localtime(consttime_t*timer);// 转换为本地时间structtm*gmtime(consttime_t*timer);// 转换为 UTC 时间两者都返回指向静态struct tm的指针,因此多次调用会覆盖同一块内存。
time_tnow=time(NULL);structtm*local=localtime(&now);printf("本地时间:%d-%02d-%02d %02d:%02d:%02d\n",local->tm_year+1900,local->tm_mon+1,local->tm_mday,local->tm_hour,local->tm_min,local->tm_sec);3.3strftime()— 格式化时间输出
size_tstrftime(char*str,size_tmaxsize,constchar*format,conststructtm*timeptr);按照指定格式将struct tm格式化为字符串,是输出时间最灵活的方式。
time_tnow=time(NULL);structtm*local=localtime(&now);charbuffer[64];strftime(buffer,sizeof(buffer),"%Y-%m-%d %H:%M:%S",local);printf("格式化时间:%s\n",buffer);常用格式说明符:
| 格式符 | 含义 | 示例 |
|---|---|---|
%Y | 四位年份 | 2026 |
%m | 两位月份(01-12) | 09 |
%d | 两位日期(01-31) | 23 |
%H | 24 小时制小时(00-23) | 11 |
%M | 分钟(00-59) | 58 |
%S | 秒(00-59) | 27 |
%A | 星期全名 | Wednesday |
%B | 月份全名 | September |
3.4mktime()— 将struct tm转回time_t
time_tmktime(structtm*timeptr);将本地时间表示的struct tm转换为time_t秒数,同时会规范化字段(如将tm_mon溢出自动进位)。
structtmt={0};t.tm_year=2026-1900;// 年份从 1900 起算t.tm_mon=8;// 9 月(0 起算)t.tm_mday=23;time_tts=mktime(&t);printf("对应时间戳:%ld\n",(long)ts);3.5difftime()— 计算时间差
doubledifftime(time_ttime1,time_ttime0);返回time1 - time0的秒数差,返回类型为double。
time_tstart=time(NULL);// 模拟耗时操作for(volatileinti=0;i<100000000;i++);time_tend=time(NULL);printf("耗时:%.2f 秒\n",difftime(end,start));3.6clock()— 测量处理器时间
clock_tclock(void);返回程序自启动以来消耗的处理器时钟数,除以CLOCKS_PER_SEC得到秒数。
clock_tstart=clock();// 模拟耗时操作for(volatileinti=0;i<100000000;i++);clock_tend=clock();printf("CPU 耗时:%.3f 秒\n",(double)(end-start)/CLOCKS_PER_SEC);3.7asctime()与ctime()— 简单字符串输出
char*asctime(conststructtm*timeptr);char*ctime(consttime_t*timer);两者都返回固定格式的字符串(如Wed Sep 23 11:58:27 2026),但包含换行符,且线程不安全,建议优先使用strftime()。
time_tnow=time(NULL);printf("ctime 输出:%s",ctime(&now));4. 综合示例:完整的日期时间工具
下面是一个综合示例,演示如何获取当前时间、格式化输出、计算时间差以及将字符串解析为时间戳。
#include<stdio.h>#include<time.h>intmain(){// 1. 获取当前时间time_tnow=time(NULL);printf("当前时间戳:%ld\n",(long)now);// 2. 转换为本地时间并格式化输出structtm*local=localtime(&now);charbuffer[64];strftime(buffer,sizeof(buffer),"%Y-%m-%d %H:%M:%S %A",local);printf("本地时间:%s\n",buffer);// 3. 计算两个时间点之间的差值structtmt1={0},t2={0};t1.tm_year=2026-1900;t1.tm_mon=8;t1.tm_mday=23;t2.tm_year=2026-1900;t2.tm_mon=8;t2.tm_mday=24;time_tts1=mktime(&t1);time_tts2=mktime(&t2);printf("两天相差:%.0f 秒\n",difftime(ts2,ts1));// 4. 测量代码段执行时间clock_tstart=clock();for(volatileinti=0;i<50000000;i++);clock_tend=clock();printf("循环耗时:%.3f 秒\n",(double)(end-start)/CLOCKS_PER_SEC);return0;}5. 注意事项
- 线程安全:
localtime()、gmtime()、asctime()、ctime()返回静态内存,多线程环境下应使用localtime_r()、gmtime_r()等可重入版本。 - 时区处理:
localtime()依赖系统时区设置,跨时区应用需谨慎。 - 精度限制:
time_t以秒为单位,高精度计时应使用<time.h>的clock_gettime()(POSIX)或 C11 的<timespec_get>。 - 年份范围:
struct tm的tm_year从 1900 起算,32 位time_t在 2038 年可能溢出,64 位系统通常无此问题。
6. 总结
<time.h>提供了从底层时间戳到高层格式化输出的完整时间处理能力。掌握time_t、struct tm两种核心类型,以及time()、localtime()、strftime()、mktime()、difftime()、clock()等常用函数,就能应对绝大多数 C 语言时间编程需求。建议在实际项目中优先使用strftime()进行格式化输出,并注意线程安全与精度问题。
二、代码示例
#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<time.h>#include<Windows.h>intmain(void){SetConsoleOutputCP(CP_UTF8);// 1. time_t:Unix时间戳,从1970-01-01 00:00:00 UTC 开始的秒数time_tnow_ts;time(&now_ts);// 获取当前系统时间戳,等价 now_ts = time(NULL);printf("1. 当前Unix时间戳(秒) = %lld\n\n",(longlong)now_ts);// 2. localtime():时间戳 →【本地时区】struct tm(年月日时分秒)structtm*local_tm_ptr=localtime(&now_ts);printf("2. localtime 本地时间:\n");printf(" 年:%d,月:%d,日:%d 时:%d:%d:%d\n",local_tm_ptr->tm_year+1900,// tm_year = 年份-1900local_tm_ptr->tm_mon+1,// tm_mon:0~11 → +1local_tm_ptr->tm_mday,local_tm_ptr->tm_hour,local_tm_ptr->tm_min,local_tm_ptr->tm_sec);printf(" 星期 tm_wday(0=周日):%d,年内第%d天\n\n",local_tm_ptr->tm_wday,local_tm_ptr->tm_yday);// 3. gmtime():时间戳 →【UTC零时区】struct tmstructtm*utc_tm_ptr=gmtime(&now_ts);printf("3. gmtime UTC零时区时间:\n");printf(" 年:%d,月:%d,日:%d 时:%d:%d:%d\n\n",utc_tm_ptr->tm_year+1900,utc_tm_ptr->tm_mon+1,utc_tm_ptr->tm_mday,utc_tm_ptr->tm_hour,utc_tm_ptr->tm_min,utc_tm_ptr->tm_sec);// 4. strftime() 格式化时间字符串(重点,前面RTDateTime用到)charbuf[64];strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",local_tm_ptr);printf("4. strftime格式化本地时间字符串:%s\n\n",buf);// 5. mktime():struct tm → time_t(反向转换!年月日转时间戳)structtmcustom_tm={0};custom_tm.tm_year=2026-1900;custom_tm.tm_mon=9-1;//9月custom_tm.tm_mday=23;custom_tm.tm_hour=10;custom_tm.tm_min=0;custom_tm.tm_sec=0;time_tcustom_ts=mktime(&custom_tm);printf("5. mktime:2026-09-23 10:00:00 对应的时间戳 = %lld\n\n",(longlong)custom_ts);// 6. difftime():计算两个time_t之间相差多少秒,返回doubletime_tt1=time(NULL);// 模拟延时,VS用Sleep,linux用sleep// Sleep(1000);time_tt2=time(NULL);doublediff_sec=difftime(t2,t1);printf("6. difftime 时间差:%.3f 秒\n\n",diff_sec);// ========== 【重要】线程安全版本演示 ==========// VS: localtime_s(&tm_safe, &now_ts);// RT-Thread/Linux: localtime_r(&now_ts, &tm_safe);structtmtm_safe;#ifdef_WIN32localtime_s(&tm_safe,&now_ts);#elselocaltime_r(&now_ts,&tm_safe);#endifstrftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",&tm_safe);printf("7. 可重入安全版本 localtime_s/r:%s\n",buf);return0;}