Извлечение года / месяца / дня и т. Д. Из std::chrono::time_point в C++

Как извлечь год, месяц, день, час, минуту, секунду и миллисекунду из std::chrono::time_point объект?

Я видел только примеры того, как извлечь общее количество, например, секунд из duration,

2 ответа

Решение

Вы можете извлечь эту информацию только из system_clock::time_point, Это единственные системные часы, которые связаны с гражданским календарем. Вот как получить текущую точку времени, используя эти часы:

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

Затем вы можете преобразовать это в time_t с:

time_t tt = system_clock::to_time_t(now);

Используя библиотеку C, вы можете преобразовать time_t к tm, но вы должны выбрать, хотите ли вы, чтобы это преобразование происходило в часовом поясе UTC или в местном часовом поясе:

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

Затем вы можете распечатать компоненты ТМ, например:

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

Дополнительно

Если вы хотите, вы можете воспользоваться этой негарантированной информацией:

Каждая реализация system_clock Я знаю, основан на времени Unix. Т.е. количество секунд с Нового года 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';
}

Это удобно для создания пользовательских duration для модельных дней:

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

Теперь вы можете получить время, начиная с эпохи, с максимально возможной точностью:

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

Затем обрежьте его до нескольких дней и вычтите это.

Затем обрежьте его до нескольких часов и вычтите это.

Продолжайте, пока вы не вычли из секунд.

То, что вы остались с доли секунды с единицами system_clock::duration, Поэтому распечатайте это значение времени выполнения и единицы времени компиляции этого значения, как показано.

Для меня эта программа распечатывает:

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

Мой вывод указывает на system_clock::duration Точность составляет микросекунды. При желании его можно урезать до миллисекунд с помощью:

milliseconds ms = duration_cast<milliseconds>(tp);

Обновить

Эта библиотека 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";
}

Который просто вывод для меня:

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

Однажды я придумал эту реализацию. Может быть, не самый лучший, но отлично подходит для моего домашнего проекта.

Можно получить все, кроме миллисекунд timeinfo и миллисекунды от ms.

      static std::wstring GetDateTime()
{
    time_t rawtime;
    struct tm timeinfo;
    wchar_t buffer[20];

    time(&rawtime);
    localtime_s(&timeinfo, &rawtime);

    auto now = std::chrono::system_clock::now();
    auto tt = std::chrono::system_clock::to_time_t(now);
    auto nowTruncated = std::chrono::system_clock::from_time_t(tt);
    auto ms = (now - nowTruncated).count();

    wcsftime(buffer, 20, L"%Y-%m-%d %H:%M:%S", &timeinfo);

    return std::wstring(buffer) + L"." + std::to_wstring(ms).substr(0, 3);
}

Пример вывода:

2021-06-25 10:18:48.295

Другие вопросы по тегам