导读:本期聚焦于小伙伴创作的《C++如何将日期格式化为字符串?strftime与put_time用法实战教程》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++如何将日期格式化为字符串?strftime与put_time用法实战教程》有用,将其分享出去将是对创作者最好的鼓励。

在C++程序开发中,将日期时间转换为指定格式的字符串是常见需求,比如生成带时间戳的日志、按日期命名的文件等场景都需要用到这个功能。C++标准库提供了两种主流的日期格式化方案,分别是C风格的strftime函数和C++11引入的put_time工具,两者都能实现日期到字符串的转换,但使用方式和适用场景有所不同。

C++如何将日期格式化为字符串?strftime与put_time用法实战教程

strftime函数基础用法

strftime是C标准库中的时间格式化函数,定义在<ctime>头文件中,它可以将time_t类型的时间按照指定的格式转换为字符串。函数的核心参数包括目标字符串缓冲区、缓冲区大小、格式字符串和时间结构体指针。

strftime函数原型

函数的基本定义如下:

#include <ctime>
#include <iostream>

// 函数原型
// size_t strftime(char* str, size_t maxsize, const char* format, const struct tm* timeptr);

基础示例:获取当前时间并格式化

下面的代码演示了使用strftime获取当前系统时间,并格式化为常见的年月日时分秒字符串:

#include <ctime>
#include <iostream>
#include <vector>

int main() {
    // 获取当前系统时间
    time_t now = time(nullptr);
    // 转换为本地时间结构体
    struct tm local_time;
    localtime_r(&now, &local_time);  // Linux/macOS使用localtime_r,线程安全
    // Windows下可使用localtime_s(&local_time, &now);

    // 定义格式字符串:年-月-日 时:分:秒
    const char* format = "%Y-%m-%d %H:%M:%S";
    // 定义缓冲区,足够存储格式化后的字符串
    char buffer[64];
    // 调用strftime格式化
    size_t ret = strftime(buffer, sizeof(buffer), format, &local_time);
    
    if (ret > 0) {
        std::cout << "格式化后的时间:" << buffer << std::endl;
    } else {
        std::cout << "时间格式化失败" << std::endl;
    }
    return 0;
}

常用格式说明符

strftime的格式字符串由普通字符和格式说明符组成,常用说明符如下:

  • %Y:四位年份,比如2024
  • %m:两位月份,01-12
  • %d:两位日期,01-31
  • %H:24小时制小时,00-23
  • %M:分钟,00-59
  • %S:秒,00-60(60用于闰秒)
  • %y:两位年份,比如24
  • %I:12小时制小时,01-12
  • %p:AM/PM标识
  • %A:完整的星期名称,比如Monday
  • %a:简写的星期名称,比如Mon
  • %B:完整的月份名称,比如January
  • %b:简写的月份名称,比如Jan

put_time工具用法

put_time是C++11标准引入的I/O操纵器,定义在<iomanip>头文件中,它可以配合输出流(比如std::cout、std::ostringstream)直接输出格式化后的时间,使用起来更符合C++的面向对象风格。

put_time基本使用

put_time需要接收两个参数,第一个是tm结构体指针,第二个是格式字符串,格式说明符和strftime完全一致。

#include <iostream>
#include <ctime>
#include <iomanip>
#include <sstream>

int main() {
    time_t now = time(nullptr);
    struct tm local_time;
    localtime_r(&now, &local_time);

    // 直接输出到控制台
    std::cout << "当前时间:" << std::put_time(&local_time, "%Y-%m-%d %H:%M:%S") << std::endl;

    // 输出到字符串流,转换为字符串
    std::ostringstream oss;
    oss << std::put_time(&local_time, "%Y%m%d_%H%M%S");
    std::string time_str = oss.str();
    std::cout << "文件名时间戳:" << time_str << std::endl;
    return 0;
}

strftime与put_time对比

两种方式都能实现日期格式化,具体差异如下:

对比项strftimeput_time
所属标准C标准库,兼容C和C++C++11及以上标准
使用方式函数调用,需要手动管理缓冲区I/O操纵器,配合流使用
返回值返回格式化后的字符数,失败返回0返回流对象,支持链式调用
适用场景需要直接获取C风格字符串、兼容旧代码C++风格代码、需要配合流输出或转换字符串
线程安全依赖传入的tm结构体,本身无状态依赖流对象,流对象需保证线程安全

实战场景示例

场景1:生成日志时间戳

日志通常需要带精确到毫秒的时间戳,strftime本身不支持毫秒,需要额外处理:

#include <ctime>
#include <iostream>
#include <chrono>
#include <fmt/format.h>  // 需要fmt库支持,若不用fmt可手动拼接毫秒

int main() {
    // 获取当前时间,包含毫秒
    auto now = std::chrono::system_clock::now();
    time_t now_time = std::chrono::system_clock::to_time_t(now);
    struct tm local_time;
    localtime_r(&now_time, &local_time);

    // 计算毫秒部分
    auto duration = now.time_since_epoch();
    auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;

    // 格式化时间+毫秒
    char buffer[64];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &local_time);
    char log_time[64];
    snprintf(log_time, sizeof(log_time), "%s.%03ld", buffer, millis);
    std::cout << "[ " << log_time << " ] 这是一条日志信息" << std::endl;
    return 0;
}

场景2:处理自定义时间结构体

如果需要对自定义的时间对象进行格式化,可以先转换为tm结构体再使用两种方式处理:

#include <ctime>
#include <iostream>
#include <iomanip>

// 自定义时间结构体
struct MyTime {
    int year;  // 实际年份,比如2024
    int month; // 1-12
    int day;   // 1-31
    int hour;  // 0-23
    int minute;// 0-59
    int second;// 0-59
};

int main() {
    MyTime t = {2024, 5, 20, 14, 30, 45};
    struct tm tm_time = {0};
    // 填充tm结构体,注意tm_year是年份减去1900,tm_mon是月份减去1
    tm_time.tm_year = t.year - 1900;
    tm_time.tm_mon = t.month - 1;
    tm_time.tm_mday = t.day;
    tm_time.tm_hour = t.hour;
    tm_time.tm_min = t.minute;
    tm_time.tm_sec = t.second;
    // 标记tm结构体已经填充完整
    tm_time.tm_isdst = -1;

    // 使用put_time格式化
    std::cout << "自定义时间格式化:" << std::put_time(&tm_time, "%Y年%m月%d日 %H时%M分%S秒") << std::endl;
    return 0;
}

注意事项

  • 使用localtime函数时需要注意线程安全问题,尽量使用localtime_r(Linux/macOS)或localtime_s(Windows)替代非线程安全的localtime
  • strftime的缓冲区大小要足够,避免格式化后的字符串过长导致缓冲区溢出
  • put_time需要C++11及以上标准支持,编译时需要开启对应的标准,比如使用-std=c++11参数
  • tm结构体的tm_year字段是年份减去1900,tm_mon字段是月份减去1,填充自定义时间时需要注意转换,否则会得到错误的结果

strftimeput_timeC++日期格式化日期转字符串修改时间:2026-07-17 14:54:45

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。