
C语言 time.h 头文件详解
- 一、头文件详解
-
- [1. 引言](#1. 引言)
- [2. 核心类型](#2. 核心类型)
-
- [2.1 `time_t`](#2.1
time_t) - [2.2 `struct tm`](#2.2
struct tm) - [2.3 `clock_t`](#2.3
clock_t)
- [2.1 `time_t`](#2.1
- [3. 常用函数](#3. 常用函数)
-
- [3.1 `time()` --- 获取当前时间](#3.1
time()— 获取当前时间) - [3.2 `localtime()` 与 `gmtime()` --- 时间转换](#3.2
localtime()与gmtime()— 时间转换) - [3.3 `strftime()` --- 格式化时间输出](#3.3
strftime()— 格式化时间输出) - [3.4 `mktime()` --- 将 `struct tm` 转回 `time_t`](#3.4
mktime()— 将struct tm转回time_t) - [3.5 `difftime()` --- 计算时间差](#3.5
difftime()— 计算时间差) - [3.6 `clock()` --- 测量处理器时间](#3.6
clock()— 测量处理器时间) - [3.7 `asctime()` 与 `ctime()` --- 简单字符串输出](#3.7
asctime()与ctime()— 简单字符串输出)
- [3.1 `time()` --- 获取当前时间](#3.1
- [4. 综合示例:完整的日期时间工具](#4. 综合示例:完整的日期时间工具)
- [5. 注意事项](#5. 注意事项)
- [6. 总结](#6. 总结)
- 二、代码示例

一、头文件详解
1. 引言
在 C 语言的标准库中,<time.h> 头文件提供了处理日期和时间的函数与类型。无论是记录程序运行耗时、生成时间戳,还是格式化输出当前时间,<time.h> 都是开发者不可或缺的工具。本文将系统讲解 <time.h> 中的核心类型、常用函数以及实际应用示例,帮助你彻底掌握 C 语言中的时间处理。
2. 核心类型
<time.h> 中定义了若干与时间相关的数据类型,理解它们是使用时间函数的前提。
2.1 time_t
time_t 是一个算术类型(通常是 long 或 long long),用于表示从 1970 年 1 月 1 日 00:00:00 UTC(Unix 纪元)起经过的秒数。它是最基础的时间表示形式。
c
#include <time.h>
time_t now;
now = time(NULL); // 获取当前时间(秒数)
2.2 struct tm
struct tm 是一个结构体,将时间拆分为年、月、日、时、分、秒等可读字段,便于程序直接访问。
c
struct tm {
int tm_sec; // 秒(0-59)
int tm_min; // 分(0-59)
int tm_hour; // 时(0-23)
int tm_mday; // 日(1-31)
int tm_mon; // 月(0-11,0 表示一月)
int tm_year; // 年(自 1900 起的年数)
int tm_wday; // 星期(0-6,0 表示星期日)
int tm_yday; // 一年中的第几天(0-365)
int tm_isdst; // 夏令时标志
};
注意:tm_mon 从 0 开始,tm_year 从 1900 开始,使用时需要相应调整。
2.3 clock_t
clock_t 用于表示处理器时钟计时单元(clock ticks),通常配合 clock() 函数测量程序运行时间。
3. 常用函数
3.1 time() --- 获取当前时间
c
time_t time(time_t *timer);
返回当前日历时间(秒数)。若 timer 不为 NULL,也会将结果写入该指针指向的变量。
c
time_t now = time(NULL);
printf("当前时间戳:%ld\n", (long)now);
3.2 localtime() 与 gmtime() --- 时间转换
c
struct tm *localtime(const time_t *timer); // 转换为本地时间
struct tm *gmtime(const time_t *timer); // 转换为 UTC 时间
两者都返回指向静态 struct tm 的指针,因此多次调用会覆盖同一块内存。
c
time_t now = time(NULL);
struct tm *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.3 strftime() --- 格式化时间输出
c
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr);
按照指定格式将 struct tm 格式化为字符串,是输出时间最灵活的方式。
c
time_t now = time(NULL);
struct tm *local = localtime(&now);
char buffer[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.4 mktime() --- 将 struct tm 转回 time_t
c
time_t mktime(struct tm *timeptr);
将本地时间表示的 struct tm 转换为 time_t 秒数,同时会规范化字段(如将 tm_mon 溢出自动进位)。
c
struct tm t = {0};
t.tm_year = 2026 - 1900; // 年份从 1900 起算
t.tm_mon = 8; // 9 月(0 起算)
t.tm_mday = 23;
time_t ts = mktime(&t);
printf("对应时间戳:%ld\n", (long)ts);
3.5 difftime() --- 计算时间差
c
double difftime(time_t time1, time_t time0);
返回 time1 - time0 的秒数差,返回类型为 double。
c
time_t start = time(NULL);
// 模拟耗时操作
for (volatile int i = 0; i < 100000000; i++);
time_t end = time(NULL);
printf("耗时:%.2f 秒\n", difftime(end, start));
3.6 clock() --- 测量处理器时间
c
clock_t clock(void);
返回程序自启动以来消耗的处理器时钟数,除以 CLOCKS_PER_SEC 得到秒数。
c
clock_t start = clock();
// 模拟耗时操作
for (volatile int i = 0; i < 100000000; i++);
clock_t end = clock();
printf("CPU 耗时:%.3f 秒\n", (double)(end - start) / CLOCKS_PER_SEC);
3.7 asctime() 与 ctime() --- 简单字符串输出
c
char *asctime(const struct tm *timeptr);
char *ctime(const time_t *timer);
两者都返回固定格式的字符串(如 Wed Sep 23 11:58:27 2026),但包含换行符,且线程不安全,建议优先使用 strftime()。
c
time_t now = time(NULL);
printf("ctime 输出:%s", ctime(&now));
4. 综合示例:完整的日期时间工具
下面是一个综合示例,演示如何获取当前时间、格式化输出、计算时间差以及将字符串解析为时间戳。
c
#include <stdio.h>
#include <time.h>
int main() {
// 1. 获取当前时间
time_t now = time(NULL);
printf("当前时间戳:%ld\n", (long)now);
// 2. 转换为本地时间并格式化输出
struct tm *local = localtime(&now);
char buffer[64];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S %A", local);
printf("本地时间:%s\n", buffer);
// 3. 计算两个时间点之间的差值
struct tm t1 = {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_t ts1 = mktime(&t1);
time_t ts2 = mktime(&t2);
printf("两天相差:%.0f 秒\n", difftime(ts2, ts1));
// 4. 测量代码段执行时间
clock_t start = clock();
for (volatile int i = 0; i < 50000000; i++);
clock_t end = clock();
printf("循环耗时:%.3f 秒\n", (double)(end - start) / CLOCKS_PER_SEC);
return 0;
}
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() 进行格式化输出,并注意线程安全与精度问题。
二、代码示例
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
#include <Windows.h>
int main(void)
{
SetConsoleOutputCP(CP_UTF8);
// 1. time_t:Unix时间戳,从1970-01-01 00:00:00 UTC 开始的秒数
time_t now_ts;
time(&now_ts); // 获取当前系统时间戳,等价 now_ts = time(NULL);
printf("1. 当前Unix时间戳(秒) = %lld\n\n", (long long)now_ts);
// 2. localtime():时间戳 →【本地时区】struct tm(年月日时分秒)
struct tm* 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 = 年份-1900
local_tm_ptr->tm_mon + 1, // tm_mon:0~11 → +1
local_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 tm
struct tm* 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用到)
char buf[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(反向转换!年月日转时间戳)
struct tm custom_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_t custom_ts = mktime(&custom_tm);
printf("5. mktime:2026-09-23 10:00:00 对应的时间戳 = %lld\n\n", (long long)custom_ts);
// 6. difftime():计算两个time_t之间相差多少秒,返回double
time_t t1 = time(NULL);
// 模拟延时,VS用Sleep,linux用sleep
// Sleep(1000);
time_t t2 = time(NULL);
double diff_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);
struct tm tm_safe;
#ifdef _WIN32
localtime_s(&tm_safe, &now_ts);
#else
localtime_r(&now_ts, &tm_safe);
#endif
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm_safe);
printf("7. 可重入安全版本 localtime_s/r:%s\n", buf);
return 0;
}

