从 C++ 中的 std::chrono::time_point 中提取年/月/日等 [英] Extract year/month/day etc. from std::chrono::time_point in C++

查看:51
本文介绍了从 C++ 中的 std::chrono::time_point 中提取年/月/日等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How can I extract the year, month, day, hour, minute, second and millisecond from an std::chrono::time_point object?

我只看到了如何提取总量的例子,例如duration 中的秒数.

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

推荐答案

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

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 now = system_clock::now();

然后您可以使用以下命令将其转换为 time_t:

You can then convert this to a time_t with:

time_t tt = system_clock::to_time_t(now);

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

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

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

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

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

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

另外

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

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

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

Every implementation of system_clock I'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:

#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 << "]
";

    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 << '
';
}

创建自定义duration 来模拟天数很方便:

It is handy to create a custom duration to model days:

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

现在您可以获取自 epoch 以来的时间,尽可能精确,使用:

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.

继续,直到减去秒数.

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

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.

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

For me this program prints out:

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

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

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

milliseconds ms = duration_cast<milliseconds>(tp);

更新

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

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

#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 << '
';
    }
    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() << '
';
    S::cout << "month       = " << ymd.month() << '
';
    S::cout << "day         = " << ymd.day() << '
';
    S::cout << "hour        = " << time.hours().count() << "h
";
    S::cout << "minute      = " << time.minutes().count() << "min
";
    S::cout << "second      = " << time.seconds().count() << "s
";
    S::cout << "millisecond = " << time.subseconds().count() << "ms
";
}

这只是为我输出:

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

另一个更新

这个库发展成为 C++ 标准提案,现在在 C++20 工作草案中.在 C++20 中从 system_clock::time_point 中提取这些字段的语法是:

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_point in C++20 will be:

#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();
}

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

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:

#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();
}

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

The only difference above is the construction of tp which now has type local_time as opposed to sys_time in the UTC example. Alternatively one could have picked an arbitrary time zone with this small change:

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

这篇关于从 C++ 中的 std::chrono::time_point 中提取年/月/日等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆