news 2026/11/5 6:52:03

C语言 <time.h> 头文件详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言 <time.h> 头文件详解

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
%H24 小时制小时(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;}


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 13:11:13

std::array 与裸数组、vector 怎么选

std::array 经常被当成「多此一举的包装」&#xff1a;既然 int a[5] 就够了&#xff0c;为什么要包一层&#xff1f;答案是两个词&#xff1a;零开销和不退化。零开销的意思是 sizeof(std::array<int, 5>) sizeof(int[5])&#xff0c;一个字节都没多&#xff1b;不退化…

作者头像 李华
网站建设 2026/11/1 19:08:37

点估计推导过程详解:从矩估计到最大似然估计

1. 什么是点估计现实中我们经常不知道总体参数&#xff0c;却能抽到样本。例如&#xff1a;想知道某厂灯泡的平均寿命 μ&#xff08;总体均值&#xff09;&#xff0c;不可能把所有灯泡都点亮测一遍&#xff1b;想知道一枚硬币是否均匀&#xff0c;即正面概率 p&#xff0c;只…

作者头像 李华
网站建设 2026/10/24 21:56:28

闪灵卡组残缺怎么办?三套实测替代方案解析

1. 项目概述&#xff1a;当“闪灵”卡组缺了那张决定胜负的卡&#xff0c;你该怎么办&#xff1f;“闪灵卡组”这个词&#xff0c;在当前主流卡牌对战圈里已经不是新鲜概念&#xff0c;它特指以《游戏王》中「闪灵」系列怪兽为核心构建的战术体系——主打高速展开、资源循环与压…

作者头像 李华
网站建设 2026/10/24 9:27:18

ARM交叉编译踩坑:-march参数写错导致Illegal instruction

1. 从一条编译报错说起&#xff1a;为什么-march写错会让人抓狂第一次在 ARM 平台上做交叉编译的人&#xff0c;大概率都会经历这样一个瞬间&#xff1a;明明代码在 x86 主机上编译得好好的&#xff0c;换成交叉工具链之后&#xff0c;要么直接报unrecognized command line opt…

作者头像 李华
网站建设 2026/10/22 20:07:13

大文件上传超时?分片上传解决方案全解析

在日常做后台管理、网盘系统、素材上传功能时&#xff0c;很多前端同学都遇到过同一个头疼问题&#xff1a;小文件上传秒成功&#xff0c;一旦上传几十MB甚至几百MB的大文件&#xff0c;大概率直接报错。要么接口请求超时&#xff0c;要么网络波动导致上传失败&#xff0c;用户…

作者头像 李华
网站建设 2026/10/25 13:06:32

C语言入门:从输入输出到条件判断

昨天讲了系统安装&#xff0c;今天可以继续讲编写程序了。昨日的作业要先去做下, 昨日这个作业, 是去编写C语言程序, 然后输出以下这样的图形。程序如下&#xff1a;怎么样&#xff1f;很简单吧&#xff1f;去重新复习一回, 每一行当中第二个双引号的前面的那个 \n 究竟是什么,…

作者头像 李华