c++ - 添加时间偏移量

标签 c++

我有一个字符串,根据某种格式将其转换为时间

 const std::string format = "%Y-%m-%dT%H:%M:%S";
    std::istringstream dateStream(date);

    std::tm tm = {}; 
    dateStream >> std::get_time(&tm, format.c_str());  

然后我想给它添加一个偏移量 并将结果打印为字符串:

 tm.tm_min += offset;
    std::mktime(&tm);

    std::ostringstream resultStream;
    resultStream << std::put_time(&tm, format.c_str());

它似乎在这里工作 https://godbolt.org/z/q7svh51Y7

但是当我在本地系统上运行它时,我收到 2023-09-26T18:18:23 而不是 2023-09-26T17:18:23 您能帮忙解决这个问题吗?

最佳答案

问题在于 C API(mktimestrftimestrptime 等)将“故障时间”与“本地时间”混为一谈。 time”,并以有趣且意想不到的方式应用 UTC 偏移量。

有两种方法可以解决这个问题:

  1. 继续使用 C API,但添加:

    std::tm tm = {}; 
    tm.tm_isdst = -1;  // Add this line
    

这有效。但这个 API 很难使用,这种类型的错误几乎肯定会再次袭击您。

  • 使用 chrono 和 C++20。但是,如果您坚持使用 C++17,可以使用 free, open-source, header-only C++20 chrono preview library与 C++11/14/17 兼容,更安全、更易于使用,并且在时机成熟时可以轻松移植到 C++20。

    #include "date/date.h"
    #include <chrono>
    #include <iostream>
    #include <sstream>
    
    std::string
    setOffsetForTime(const std::string& date, const std::chrono::seconds offset)
    {
        const std::string format = "%Y-%m-%dT%H:%M:%S";
        std::istringstream dateStream(date);
    
        date::sys_seconds tm = {}; 
        dateStream >> date::parse(format, tm);  
    
        tm += offset;
    
        std::ostringstream resultStream;
        resultStream << date::format(format, tm);
        return resultStream.str();
    }
    
    int main() {
        std::string dateString1 = "2023-09-26T11:48:23";
        const std::chrono::minutes offset{330};
        std::cout<< setOffsetForTime(dateString1, offset);
    
        return 0;
    }
    
  • 正如您所看到的,新代码的结构与您已有的代码没有什么不同。但以下是重要的区别:

    A.它使用类型安全的时间单位,例如分钟,而不是int

    B. sys_seconds 类型具有 UTC 时间点的语义。不涉及时区。如果您想要转换为本地时间,则需要在代码中显式执行,而不是隐式执行。

    要将其移植到 C++20,您需要删除 #include "date/date.h" 并将几个 date:: 更改为 std::计时::。并且 format 字符串需要针对格式化语句稍作更改:"{:%Y-%m-%dT%H:%M:%S}" .

    Demo of ported C++20 code.

    关于c++ - 添加时间偏移量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77229156/

    相关文章:

    c++ - 使用基类对象调用派生类函数

    java - 基于终端的角色扮演游戏

    c++ - 我的回击不起作用?

    c++ - 将指向成员函数的指针传递给模板

    c++ - 检查应用程序是否安装在 MAC OS X 上的替代方法?

    c++ - 同时声明和定义 C++ 数组

    c++ - staticMetaObject 函数外部的 Qt5 未解析

    c++ - 如何覆盖 C++ 模板类中的纯虚函数?

    c++ - QMediaPlayer 在 sleep 前不播放

    c++ - OpenCV Mat to ffmpeg AVPicture 转换内存泄漏