如何转换date::year_month_day到chrono time_point

How to convert date::year_month_day to chrono time_point

提问人:afp_2008 提问时间:11/10/2023 最后编辑:afp_2008 更新时间:11/10/2023 访问量:92

问:

我正在尝试将 Howard Hinnant 先生的图书馆转换为 ,但没有成功。最终,我想从UTC时区的时间点开始计算。date::year_month_daystd::chrono::system_clock::time_pointtime_since_epoch().count()

我下面的代码可以完成这项工作(结果是在我的本地时区),但如果它提供这样的功能,我最好使用库。date

    date::year_month_day _ymd = date::year{2023}/11/9; // November 9, 2023

    // Modern C++
    // The following returns 16994880000000000
    // = Thursday, July 16, 1970 4:48:00 PM, which is not 2023/11/09
    std::chrono::system_clock::time_point tp = 
            std::chrono::time_point<std::chrono::system_clock, std::chrono::days>(std::chrono::sys_days{_ymd});

    // Classic C++
    // The following returns 1702108800
    // = Saturday, December 9, 2023 8:00:00 AM, which of course is not 2023/11/09
    struct tm t = {0};
    t.tm_year = _ymd.year().operator int() - 1900;
    t.tm_mon = _ymd.month().operator unsigned int();
    t.tm_mday = _ymd.day().operator unsigned int();
    time_t timeSinceEpoch = mktime(&t);
    std::cout << "timeSinceEpoch " << timeSinceEpoch << "\n"; // it will be in my time zone, not UTC
C++ 日期时间 C++-Chrono

评论


答:

5赞 Howard Hinnant 11/10/2023 #1

我注意到你使用的是 Windows。最新版本的 MSVC 附带了 C++20 的完整实现。这过时了我的日期库。我的建议是使用 C++20 。虽然如果由于某种原因你不能,我很乐意提供帮助。<chrono><chrono>

您的第一次尝试是正确的。但出于某种原因,它对你来说似乎是不正确的:

date::year_month_day _ymd = date::year{2023}/11/9; // November 9, 2023

// Modern C++
// The following returns 16994880000000000
// = Thursday, July 16, 1970 4:48:00 PM, which is not 2023/11/09
std::chrono::system_clock::time_point tp = 
        std::chrono::time_point<std::chrono::system_clock, std::chrono::days>(std::chrono::sys_days{_ymd});

Windows 以 1/10 微秒(分微秒)的刻度计数。这些刻度16994880000000000是 2023-11-09 00:00:00.00000000 UTC。从您的评论中,您似乎将16994880000000000解释为纳秒而不是分微秒。如果您显示为您解释16994880000000000的代码,那将会有所帮助。system_clock::time_point

虽然你的代码是正确的,但它也过于冗长。在不改变功能的情况下,它可以简化为:

std::chrono::system_clock::time_point tp = std::chrono::sys_days{_ymd};

该类型是 的类型别名。因此,您实际上只是插入了一个无偿的复制结构。sys_daystime_point<system_clock, days>

如果您希望结果以纳秒为单位,这也很容易做到:

std::chrono::sys_time<std::chrono::nanoseconds> tp = std::chrono::sys_days{_ymd};

现在是1699488000000000000(末尾还有两个零)。tp.time_since_epoch().count()

评论

1赞 afp_2008 11/10/2023
我正在为 Windows 和 Linux 开发。我在两个操作系统中都有 C++20,但我的 GCC11 没有带有 chrono 日期库的 C++20。在我的 中,我有但仍然我的 GCC 抱怨使用日期库的命名空间。CMakeLists.txtset(CMAKE_CXX_STANDARD 20)/opt/rh/devtoolset-11/root/usr/bin/gccchrono
1赞 Howard Hinnant 11/10/2023
好的,Linux的精度很高。我猜这就是你误解16994880000000000的方式:通过将其从 Windows 传递到 Linux。如果您在两个平台上使用(代替),这将解决该问题。system_clock::time_pointnanosecondsdate::sys_time<std::chrono::nanoseconds>system_clock::time_point
1赞 Howard Hinnant 11/10/2023
除了在线编译器,我不使用 Linux。但是我可以告诉你,当 gcc-14 发布时,它将包括完整的 C++20 库。<chrono>
1赞 Howard Hinnant 11/10/2023
这里有一个适用于 Linux 的好工具: wandbox.org/permlink/RBz9k4XnHlw5OYY9
1赞 afp_2008 11/10/2023
非常感谢您回馈社会。非常感谢你所有的出色工作,Hinnant先生。