技术分享:深入C++时间操作函数的应用与实践

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 技术分享:深入C++时间操作函数的应用与实践

在软件开发中,时间是无处不在的一个概念,无论是日志记录、定时任务还是用户界面,时间的处理都至关重要。C++标准库提供了一套完整的工具来帮助我们处理时间相关的操作。本文将详细介绍几个时间操作函数的使用场景、代码实现以及它们在实际开发中的应用。

函数列表与使用场景

  1. 判断当前秒数是否是指定的秒数-isCurrentSecond
  • 使用场景:定时任务触发、性能测试中的特定时间点检查等。
  1. 获取当前时间的分钟部分-getCurrentTimeMinute
  • 使用场景:生成时间戳、日志记录、定时备份等。
  1. 将time_point转换为格式化的字符串-formatTimePoint
  • 使用场景:日志输出、用户界面显示、数据格式化等。
  1. 获取两个时间点之间的所有分钟字符串-getMinutesInRange
  • 使用场景:生成时间范围内的报告、时间序列分析等。
  1. 将时间字符串转换为MySQL的DATETIME格式-convertToMySqlDateTime
  • 使用场景:数据库时间数据的插入、更新等操作。
  1. 检查输入数据是否是合法的年月日时分秒-isValidDateTime
  • 使用场景:用户输入验证、数据导入前的数据校验等。

代码实现与注释

以下是每个函数的详细介绍和注释。

1. 判断当前秒数是否是指定的秒数
bool isCurrentSecond(int targetSecond) {
    // 获取当前时间点
    auto now = std::chrono::system_clock::now();
    // 转换为time_t类型
    std::time_t nowTimeT = std::chrono::system_clock::to_time_t(now);
    // 转换为tm结构体
    struct tm nowTm;
    localtime_r(&nowTimeT, &nowTm); // 使用localtime_r是线程安全的

    // 获取当前的秒数
    int currentSecond = nowTm.tm_sec;

    // 判断当前秒数是否是指定的秒数
    return currentSecond == targetSecond;
}
2. 获取当前时间的分钟部分
std::string getCurrentTimeMinute() {
    // 获取当前时间点
    auto now = std::chrono::system_clock::now();
    // 转换为time_t类型
    std::time_t nowTimeT = std::chrono::system_clock::to_time_t(now);
    // 转换为tm结构体
    struct tm nowTm;
    gmtime_r(&nowTimeT, &nowTm); // 使用gmtime_r来避免时区的影响

    // 使用stringstream和iomanip来格式化时间字符串为"YYYYMMDDHHMM"格式
    std::stringstream ss;
    ss << std::put_time(&nowTm, "%Y%m%d%H%M");

    // 返回格式化的时间字符串
    return ss.str();
}
3. 将time_point转换为格式化的字符串
std::string formatTimePoint(const std::chrono::system_clock::time_point& timePoint) {
    // 将time_point转换为time_t
    auto tt = std::chrono::system_clock::to_time_t(timePoint);
    // 使用gmtime来避免时区问题
    std::tm tm = *std::gmtime(&tt);

    // 使用stringstream和put_time来格式化时间为"YYYYMMDDHHMM"格式
    std::stringstream ss;
    ss << std::put_time(&tm, "%Y%m%d%H%M");

    // 返回格式化的时间字符串
    return ss.str();
}
4. 获取两个时间点之间的所有分钟字符串
std::vector<std::string> getMinutesInRange(const std::string& startTimeStr, const std::string& endTimeStr) {
    // 解析时间字符串为time_point
    std::tm startTimeTm, endTimeTm;
    std::istringstream ssStartTime(startTimeStr);
    std::istringstream ssEndTime(endTimeStr);

    // 使用get_time来解析时间字符串
    ssStartTime >> std::get_time(&startTimeTm, "%Y%m%d%H%M");
    ssEndTime >> std::get_time(&endTimeTm, "%Y%m%d%H%M");

    // 转换tm结构体为time_point
    std::chrono::system_clock::time_point startTime = std::chrono::system_clock::from_time_t(std::mktime(&startTimeTm));
    std::chrono::system_clock::time_point endTime = std::chrono::system_clock::from_time_t(std::mktime(&endTimeTm));

    // 存储分钟字符串的向量
    std::vector<std::string> minutes;

    // 循环遍历两个时间点之间的每一分钟
    for (auto currentTime = startTime; currentTime <= endTime; currentTime += std::chrono::minutes(1)) {
        // 将当前时间点格式化为字符串并添加到向量中
        minutes.push_back(formatTimePoint(currentTime));
    }

    // 返回包含所有分钟字符串的向量
    return minutes;
}
5. 将时间字符串转换为MySQL的DATETIME格式
std::string convertToMySqlDateTime(const std::string &timeStr, bool forceFormat = false) {
    // MySQL的DATETIME格式为"YYYY-MM-DD HH:MM:SS"
    const std::string mysqlFormat = "%Y-%m-%d %H:%M:%S";
    std::istringstream iss(timeStr);
    int year, month, day, hour, minute, second;
    char dash1, dash2, colon1, colon2;

    // 如果需要强制格式化,则调整输入字符串
    if (forceFormat) {
        if (timeStr.length() < 14) {
            // 如果时间字符串长度不足14位,则补零
            std::string paddedStr = timeStr;
            paddedStr.resize(14, '0');
            iss.str(paddedStr);
        } else if (timeStr.length() > 14) {
            // 如果时间字符串长度超过14位,则截断
            iss.str(timeStr.substr(0, 14));
        }
    }

    // 解析时间字符串
    if (!(iss >> year >> dash1 >> month >> dash2 >> day >> colon1 >> hour >> colon2 >> minute >> second)) {
        // 如果解析失败,返回空字符串
        return "";
    }

    // 构建MySQL的DATETIME格式字符串
    std::ostringstream oss;
    oss << std::setfill('0') << std::setw(4) << year << "-"
        << std::setw(2) << month << "-"
        << std::setw(2) << day << " "
        << std::setw(2) << hour << ":"
        << std::setw(2) << minute << ":"
        << std::setw(2) << second;

    // 返回格式化后的字符串
    return oss.str();
}
6. 检查输入数据是否是合法的年月日时分秒
bool isValidDateTime(const std::string &timeStr) {
    // 设置istringstream以两位数字的格式提取日期和时间的各个部分
    std::istringstream iss(timeStr);
    int year, month, day, hour, minute, second;
    char dash1, dash2, colon1, colon2;

    // 解析时间字符串
    if (!(iss >> std::setw(4) >> year >> dash1 >> std::setw(2) >> month >> dash2 >> std::setw(2) >> day
          >> colon1 >> std::setw(2) >> hour >> colon2 >> std::setw(2) >> minute >> second)) {
        // 如果解析失败,返回false
        return false;
    }

    // 检查年份是否在合理的范围内
    if (year < 0 || year > 9999) return false;

    // 检查月份是否在1到12之间
    if (month < 1 || month > 12) return false;

    // 检查日期是否在1到31之间
    if (day < 1 || day > 31) return false;

    // 检查小时是否在0到23之间
    if (hour < 0 || hour > 23) return false;

    // 检查分钟和秒是否在0到59之间
    if (minute < 0 || minute > 59) return false;
    if (second < 0 || second > 59) return false;

    // 如果所有检查都通过,则返回true
    return true;
}

结论

通过上述函数的介绍和代码实现,我们可以看到C++标准库在处理时间方面的功能是非常全面和强大的。这些函数不仅可以帮助我们完成日常的时间处理任务,还可以在复杂的时间计算和格式化中发挥重要作用。希望这篇技术分享能够帮助你更好地理解和使用C++中的时间操作函数。

点赞过20 直接分享源码库。


分享一个有趣的 学习链接


目录
相关文章
|
2月前
|
存储 并行计算 安全
C++多线程应用
【10月更文挑战第29天】C++ 中的多线程应用广泛,常见场景包括并行计算、网络编程中的并发服务器和图形用户界面(GUI)应用。通过多线程可以显著提升计算速度和响应能力。示例代码展示了如何使用 `pthread` 库创建和管理线程。注意事项包括数据同步与互斥、线程间通信和线程安全的类设计,以确保程序的正确性和稳定性。
|
2月前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
2月前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
79 6
|
2月前
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
37 0
C++ 多线程之线程管理函数
|
2月前
|
编译器 C语言 C++
C++入门3——类与对象2-2(类的6个默认成员函数)
C++入门3——类与对象2-2(类的6个默认成员函数)
38 3
|
2月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
345 1
|
2月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
60 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
24天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
38 2
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
83 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
80 4