Как я могу извлечь год, месяц, день, час, минуту, секунду и миллисекунду из объекта std::chrono::time_point
?
Я только видел примеры того, как извлечь общее количество, например. секунд от duration
.
Как я могу извлечь год, месяц, день, час, минуту, секунду и миллисекунду из объекта std::chrono::time_point
?
Я только видел примеры того, как извлечь общее количество, например. секунд от duration
.
Вы можете извлечь эту информацию только из 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
о 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
Другое обновление
Эта библиотека превратилась в стандартное предложение C++ и в настоящее время находится в рабочем проекте C++ 20. Синтаксис для извлечения этих полей из system_clock::time_point
в C++ 20 будет:
#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. Если вы предпочитаете их в другом часовом поясе, это также будет возможно. Например, вот как это сделать в текущем часовом поясе вашего компьютера:
#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
а не sys_time
в примере UTC. В качестве альтернативы можно было бы выбрать произвольный часовой пояс с этим небольшим изменением:
auto tp = zoned_time{"Europe/London", system_clock::now()}.get_local_time();