c语言strftime函数如何正确使用?

99ANYc3cd6
预计阅读时长 16 分钟
位置: 首页 C语言 正文

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

c语言strftime
(图片来源网络,侵删)

函数原型

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 = 123tm_mon 是从 0 开始的,10 月应该是 9

c语言strftime
(图片来源网络,侵删)

完整示例代码

下面是一个完整的 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
缓冲区不足,格式化失败。

重要注意事项

  1. 缓冲区大小:始终确保你的目标缓冲区 str 足够大,以容纳最坏情况下的格式化字符串,一个常见的做法是定义一个足够大的数组,char buffer[256];
  2. 返回值检查:在编程实践中,最好检查 strftime 的返回值,以防缓冲区溢出,如果返回值为 0,说明格式化失败。
  3. localtime 的线程安全性localtime 函数使用一个静态的内部缓冲区来存储结果,这在多线程程序中是不安全的,如果需要在多线程环境中使用,应该使用 localtime_r(POSIX 标准)或 localtime_s(MSVC 标准)等线程安全的替代函数。
  4. 本地化strftime 的输出(如 %A, %B, %p 等)会受到程序当前区域设置(locale)的影响,如果你需要固定为英文,可以在程序开始时调用 setlocale(LC_TIME, "C");setlocale(LC_TIME, "en_US.UTF-8");

希望这个详细的解释能帮助你完全掌握 strftime 函数的使用!

-- 展开阅读全文 --
头像
wprintf在C语言中如何正确使用宽字符输出?
« 上一篇 04-20
mousemsg在C语言中如何使用?
下一篇 » 04-20

相关文章

取消
微信二维码
支付宝二维码

目录[+]