strftime 是 C 标准库中的一个非常有用的函数,它用于将 struct tm 结构体中的时间信息格式化成一个我们自定义的字符串,这在进行日志记录、显示时间戳等任务时非常常见。

(图片来源网络,侵删)
函数原型
strftime 函数在 <time.h> 头文件中声明。
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr);
参数详解
| 参数 | 类型 | 描述 |
|---|---|---|
str |
char * |
这是一个字符数组(缓冲区),strftime 会将格式化后的时间字符串写入到这个数组中。 |
maxsize |
size_t |
指定 str 缓冲区的最大容量(包括结尾的 \0),如果格式化后的字符串长度超过这个值,strftime 会返回 0,str 的内容不会被写入(或写入不完整)。 |
format |
const char * |
这是一个格式化字符串,它由普通的字符和特殊的格式说明符(以 开头)组成。strftime 会根据这些说明符来替换成对应的时间信息。 |
timeptr |
const struct tm * |
这是一个指向 struct tm 结构体的指针。strftime 会从这个结构体中读取时间信息(年、月、日、时、分、秒等)来进行格式化。注意:struct tm 通常不是直接从系统时间获取的,而是通过 localtime() 或 gmtime() 等函数转换而来。 |
返回值
- 成功:返回写入到
str缓冲区中的字符个数(不包括结尾的\0)。 - 失败:如果生成的字符串长度(包括
\0)超过了maxsize,则返回 0,str的内容不会被修改(或修改不完整)。
格式说明符
strftime 的强大之处在于其丰富的格式说明符,下面是一些最常用的:
| 格式说明符 | 描述 | 示例 (假设今天是 2025年10月27日, 15:30:45) |
|---|---|---|
%Y |
4位数的年份 | 2025 |
%y |
2位数的年份 (00-99) | 23 |
%m |
2位数的月份 (01-12) | 10 |
%B |
完整的月份名称 (本地化) | October |
%b |
缩写的月份名称 (本地化) | Oct |
%d |
2位数的日期 (01-31) | 27 |
%j |
一年中的第几天 (001-366) | 300 |
%U |
一年中的第几周 (周日为每周第一天, 00-53) | 43 |
%W |
一年中的第几周 (周一为每周第一天, 00-53) | 43 |
%w |
一周中的第几天 (0代表周日, 6代表周六) | 5 |
%A |
完整的星期名称 (本地化) | Friday |
%a |
缩写的星期名称 (本地化) | Fri |
%H |
24小时制的小时 (00-23) | 15 |
%I |
12小时制的小时 (01-12) | 03 |
%M |
分钟 (00-59) | 30 |
%S |
秒 (00-60, 60用于闰秒) | 45 |
%p |
AM 或 PM (本地化) | PM |
%X |
时间部分 (HH:MM:SS) | 15:30:45 |
%x |
日期部分 (MM/DD/YY 或类似格式,本地化) | 10/27/23 |
%c |
完整的日期和时间表示 (本地化) | Fri Oct 27 15:30:45 2025 |
%F |
等价于 %Y-%m-%d |
2025-10-27 |
%T |
等价于 %H:%M:%S |
15:30:45 |
| 输出一个百分号 |
struct tm 结构体
strftime 的输入是 struct tm,这个结构体定义如下:
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; // 夏令时标志 (>0: 夏令时, 0: 非夏令时, <0: 未知)
};
特别注意:tm_year 是从 1900 年开始的,所以如果你要表示 2025 年,tm_year 应该是 2025 - 1900 = 123。tm_mon 是从 0 开始的,10 月应该是 9。

(图片来源网络,侵删)
完整示例代码
下面是一个完整的 C 语言示例,演示了如何使用 localtime() 获取本地时间,并用 strftime 进行格式化。
#include <stdio.h>
#include <time.h> // 包含 time.h 头文件
int main() {
// 1. 获取当前时间(从1970年1月1日至今的秒数)
time_t rawtime;
time(&rawtime);
// 2. 将 time_t 转换为本地时间的 struct tm 结构体
struct tm *timeinfo = localtime(&rawtime);
// 3. 定义一个足够大的缓冲区来存放格式化后的字符串
char buffer[80];
// 4. 使用 strftime 进行格式化
// 格式: YYYY-MM-DD HH:MM:SS
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeinfo);
printf("标准格式: %s\n", buffer);
// 5. 另一种格式: Month Day, Year
strftime(buffer, sizeof(buffer), "%B %d, %Y", timeinfo);
printf("另一种格式: %s\n", buffer);
// 6. 带星期的格式
strftime(buffer, sizeof(buffer), "%a, %b %d, %Y", timeinfo);
printf("带星期的格式: %s\n", buffer);
// 7. 带时间的12小时制格式
strftime(buffer, sizeof(buffer), "%I:%M:%S %p", timeinfo);
printf("12小时制时间: %s\n", buffer);
// 8. 测试缓冲区不足的情况
// 格式字符串很长,超过了缓冲区大小
strftime(buffer, 10, "This is a very long format string that will not fit", timeinfo);
if (strftime(buffer, 10, "This is a very long format string that will not fit", timeinfo) == 0) {
printf("缓冲区不足,格式化失败,\n");
} else {
printf("意外成功: %s\n", buffer);
}
return 0;
}
运行结果示例(会根据你的运行时间和系统语言环境有所不同):
标准格式: 2025-10-27 15:30:45
另一种格式: October 27, 2025
带星期的格式: Fri, Oct 27, 2025
12小时制时间: 03:30:45 PM
缓冲区不足,格式化失败。
重要注意事项
- 缓冲区大小:始终确保你的目标缓冲区
str足够大,以容纳最坏情况下的格式化字符串,一个常见的做法是定义一个足够大的数组,char buffer[256];。 - 返回值检查:在编程实践中,最好检查
strftime的返回值,以防缓冲区溢出,如果返回值为 0,说明格式化失败。 localtime的线程安全性:localtime函数使用一个静态的内部缓冲区来存储结果,这在多线程程序中是不安全的,如果需要在多线程环境中使用,应该使用localtime_r(POSIX 标准)或localtime_s(MSVC 标准)等线程安全的替代函数。- 本地化:
strftime的输出(如%A,%B,%p等)会受到程序当前区域设置(locale)的影响,如果你需要固定为英文,可以在程序开始时调用setlocale(LC_TIME, "C");或setlocale(LC_TIME, "en_US.UTF-8");。
希望这个详细的解释能帮助你完全掌握 strftime 函数的使用!
