从 C++ 中的 std::chrono::time_point 中提取年/月/日等

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15957805/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:55:43  来源:igfitidea点击:

Extract year/month/day etc. from std::chrono::time_point in C++

c++timec++11chrono

提问by bytecode77

How can I extract the year, month, day, hour, minute, second and millisecondfrom an std::chrono::time_pointobject?

如何从对象中提取年、月、日、时、分、秒和毫秒std::chrono::time_point

I only saw examples on how to extract the total amount of e.g. seconds from a duration.

我只看到了如何从duration.

回答by Howard Hinnant

You can only extract this information from a system_clock::time_point. This is the only system-supplied clock that has a relationship with the civil calendar. Here is how to get the current time_point using this clock:

您只能从system_clock::time_point. 这是系统提供的唯一与民用日历有关系的时钟。以下是使用此时钟获取当前 time_point 的方法:

 system_clock::time_point now = system_clock::now();

You can then convert this to a time_twith:

然后,您可以将其转换为time_t

time_t tt = system_clock::to_time_t(now);

Using the C library you can then convert a time_tto a tm, but you must choose whether you want that conversion to happen in the UTC timezone, or you local timezone:

使用 C 库,您可以将 a 转换time_t为 a tm,但您必须选择是希望在 UTC 时区还是本地时区中进行该转换:

tm utc_tm = *gmtime(&tt);
tm local_tm = *localtime(&tt);

Then you can print out the components of the tm, for example:

然后就可以打印出tm的组件了,例如:

std::cout << local_tm.tm_year + 1900 << '\n';
std::cout << local_tm.tm_mon + 1 << '\n';
std::cout << local_tm.tm_mday << '\n';

Additionally

此外

If you want, you can take advantage of this non-guaranteed information:

如果需要,您可以利用以下非保证信息:

Every implementation of system_clockI'm aware of is based on unix time. I.e. the number of seconds since New Years 1970 UTC, neglecting leap seconds. And the precision of this count is usually finer than seconds. Here is a complete program which extracts all of this information:

system_clock我所知道的每个实现都基于unix time。即自 UTC 新年 1970 年以来的秒数,忽略闰秒。而且这个计数的精度通常比秒要好。这是一个完整的程序,可以提取所有这些信息:

#include <chrono>
#include <ctime>
#include <iostream>

int
main()
{
    using namespace std;
    using namespace std::chrono;
    typedef duration<int, ratio_multiply<hours::period, ratio<24> >::type> days;
    system_clock::time_point now = system_clock::now();
    system_clock::duration tp = now.time_since_epoch();
    days d = duration_cast<days>(tp);
    tp -= d;
    hours h = duration_cast<hours>(tp);
    tp -= h;
    minutes m = duration_cast<minutes>(tp);
    tp -= m;
    seconds s = duration_cast<seconds>(tp);
    tp -= s;
    std::cout << d.count() << "d " << h.count() << ':'
              << m.count() << ':' << s.count();
    std::cout << " " << tp.count() << "["
              << system_clock::duration::period::num << '/'
              << system_clock::duration::period::den << "]\n";

    time_t tt = system_clock::to_time_t(now);
    tm utc_tm = *gmtime(&tt);
    tm local_tm = *localtime(&tt);
    std::cout << utc_tm.tm_year + 1900 << '-';
    std::cout << utc_tm.tm_mon + 1 << '-';
    std::cout << utc_tm.tm_mday << ' ';
    std::cout << utc_tm.tm_hour << ':';
    std::cout << utc_tm.tm_min << ':';
    std::cout << utc_tm.tm_sec << '\n';
}

It is handy to create a custom durationto model days:

创建自定义duration模型天很方便:

typedef duration<int, ratio_multiply<hours::period, ratio<24> >::type> days;

Now you can get the time since the epoch, to as fine a precision as it can manage, with:

现在,您可以获得自纪元以来的时间,尽可能精确地管理,使用:

system_clock::duration tp = now.time_since_epoch();

Then truncate it to days, and subtract that off.

然后将其截断为天,然后将其减去。

Then truncate it to hours, and subtract that off.

然后将其截断为小时,然后将其减去。

Continue until you've subtracted off the seconds.

继续,直到您减去秒数。

What you're left with is the fraction of a second with the units of system_clock::duration. So print out that run time value and the compile time units of that value as shown.

剩下的是以system_clock::duration.为单位的几分之一秒。因此打印出该运行时间值和该值的编译时间单位,如图所示。

For me this program prints out:

对我来说,这个程序打印出来:

15806d 20:31:14 598155[1/1000000]
2013-4-11 20:31:14

My output indicates the system_clock::durationprecision is microseconds. If desired, that can be truncated to milliseconds with:

我的输出表明system_clock::duration精度是微秒。如果需要,可以使用以下命令将其截断为毫秒:

milliseconds ms = duration_cast<milliseconds>(tp);

Update

更新

This header-only C++11/14 libraryencapsulates the work above, reducing client work down to:

这个只有头文件的 C++11/14 库封装了上述工作,将客户端工作减少到:

#include "date.h"
#include <iostream>

int
main()
{
    // Reduce verbosity but let you know what is in what namespace
    namespace C = std::chrono;
    namespace D = date;
    namespace S = std;

    auto tp = C::system_clock::now(); // tp is a C::system_clock::time_point
    {
        // Need to reach into namespace date for this streaming operator
        using namespace date;
        S::cout << tp << '\n';
    }
    auto dp = D::floor<D::days>(tp);  // dp is a sys_days, which is a
                                      // type alias for a C::time_point
    auto ymd = D::year_month_day{dp};
    auto time = D::make_time(C::duration_cast<C::milliseconds>(tp-dp));
    S::cout << "year        = " << ymd.year() << '\n';
    S::cout << "month       = " << ymd.month() << '\n';
    S::cout << "day         = " << ymd.day() << '\n';
    S::cout << "hour        = " << time.hours().count() << "h\n";
    S::cout << "minute      = " << time.minutes().count() << "min\n";
    S::cout << "second      = " << time.seconds().count() << "s\n";
    S::cout << "millisecond = " << time.subseconds().count() << "ms\n";
}

Which just output for me:

这只是为我输出:

2015-07-10 20:10:36.023017
year        = 2015
month       = Jul
day         = 10
hour        = 20h
minute      = 10min
second      = 36s
millisecond = 23ms

Another Update

另一个更新

This library grew into a C++ standards proposal and is now in the C++20 working draft. The syntax for extracting these fields from a system_clock::time_pointin C++20 will be:

该库发展成为 C++ 标准提案,现在处于 C++20 工作草案中。从system_clock::time_pointC++20 中的a中提取这些字段的语法是:

#include <chrono>

int
main()
{
    using namespace std::chrono;
    auto tp = system_clock::now();
    auto dp = floor<days>(tp);
    year_month_day ymd{dp};
    hh_mm_ss time{floor<milliseconds>(tp-dp)};
    auto y = ymd.year();
    auto m = ymd.month();
    auto d = ymd.day();
    auto h = time.hours();
    auto M = time.minutes();
    auto s = time.seconds();
    auto ms = time.subseconds();
}

The above assumes you want these fields in UTC. If you prefer them in some other time zone, that will also be possible. For example, here is how to do it in your computer's current local time zone:

以上假设您需要 UTC 格式的这些字段。如果您更喜欢在其他时区使用它们,那也是可能的。例如,以下是如何在您计算机的当前本地时区执行此操作:

#include <chrono>

int
main()
{
    using namespace std::chrono;
    auto tp = zoned_time{current_zone(), system_clock::now()}.get_local_time();
    auto dp = floor<days>(tp);
    year_month_day ymd{dp};
    hh_mm_ss time{floor<milliseconds>(tp-dp)};
    auto y = ymd.year();
    auto m = ymd.month();
    auto d = ymd.day();
    auto h = time.hours();
    auto M = time.minutes();
    auto s = time.seconds();
    auto ms = time.subseconds();
}

The only difference above is the construction of tpwhich now has type local_timeas opposed to sys_timein the UTC example. Alternatively one could have picked an arbitrary time zone with this small change:

上面唯一的区别是它的构造tp现在具有类型local_time,而不是sys_time在 UTC 示例中。或者,可以通过这个小的变化选择一个任意的时区:

auto tp = zoned_time{"Europe/London", system_clock::now()}.get_local_time();