Как преобразовать ГГГГ/ММ/ДД ЧЧ:ММ:СС в std::chrono::system_clock::time_point?

Я получаю компоненты ГГГГ/ММ/ДД ЧЧ:ММ:СС с внешнего чипа часов реального времени. Я хочу преобразовать это в std::chrono::system_clock::timepoint, чтобы я мог получить секунды с начала эпохи и обновить время операционной системы.

Я хотел бы использовать предложенный Говардом Хиннантом date для выполнения этого преобразования.

Я бы интуитивно сделал что-то вроде этого:

date::year_month_day ymd = ...;
date::time_of_day tod = ...;
auto sysTime = date + tod;

но я не вижу подходящей перегрузки operator+ для этого. Я что-то упускаю?

Другой пример использования этого типа преобразования — преобразование даты и времени календаря в std::chrono::timepoint, которые я могу передать в boost::asio::steady_timer.


person Emile Cormier    schedule 29.07.2015    source источник


Ответы (1)


Обычно time_of_day используется только для форматирования длительности в hh:mm:ss.fff для вывода. Но можно превратить time_of_day обратно в std::chrono::duration:

auto tod = make_time(hours{17} + minutes{16} + seconds{45});  // time_of_day
auto d = seconds(tod);                                        // seconds

В C++14 я бы использовал более краткое: 17h + 16min + 45s, но, поскольку вы упомянули, что вы были в C++11, я буду придерживаться кода C++11.

year_month_day можно преобразовать в sys_days с помощью:

auto ymd = jul/29/2015;
auto dp = sys_days{ymd};

А sys_days — это не что иное, как system_clock::time_point, но с разрешением days вместо microseconds или nanoseconds.

Затем вы можете добавить sys_days и duration и назначить их system_clock::time_point. Собираем все вместе:

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

int
main()
{
   using namespace date;
   using namespace std::chrono;
   auto ymd = jul/29/2015;
   auto tod = make_time(hours{17} + minutes{16} + seconds{45});
   system_clock::time_point tp =  sys_days(ymd) + seconds(tod);
}

В этом упрощенном примере нет необходимости проходить через time_of_day, и вы можете просто остаться с durations:

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

int
main()
{
   using namespace date;
   using namespace std::chrono;
   auto ymd = jul/29/2015;
   system_clock::time_point tp = sys_days(ymd)
                               + hours{17} + minutes{16} + seconds{45};
}

Главное помнить, что sys_days — это всего лишь грубое system_clock::time_point, и когда вы конвертируете в это из year_month_day, то вы полностью попадаете в систему std::chrono и оттуда можете делать с time_point и duration все, что хотите.

person Howard Hinnant    schedule 29.07.2015
comment
auto ymd = jul/29/2015; Что это за уродство :( - person Lightness Races in Orbit; 30.07.2015
comment
Это не чудовище, это недвусмысленный литерал даты. Если вы хотите быть более похожим на ISO-8601, вы можете вместо этого использовать 2015_y/7/29. Жаль, что 2015_y/09/29 не будет работать, а 2015_y/07/29 будет. ;) - person Ville Voutilainen; 30.07.2015
comment
@LightnessRacesinOrbit: я выбрал один из трех порядков, используемых во всем мире, которые мне были удобны. Пожалуйста, используйте тот, который вам удобен, как показывает Вилле. :-) - person Howard Hinnant; 30.07.2015
comment
@VilleVoutilainen: В этой форме это недвусмысленно, да, но я думал, что мы все давно согласились, что m/d/y в любой форме глупо, опасно и в общем случае сбивает с толку. Даже если вы устранили неоднозначность одного из компонентов! Давайте придерживаться y/m/d или d/m/y или y-m-d eh ;p Не слишком знакомы с этими новыми литералами даты; на первый взгляд они кажутся подверженными ошибкам. - person Lightness Races in Orbit; 30.07.2015
comment
@LightnessRacesinOrbit: см. en.wikipedia.org/wiki/Date_format_by_country, чтобы узнать порядок байтов даты, использовать эту планету. Также см. howardhinnant.github.io/date_v2.html для пояснений, касающихся подверженности ошибкам. этих литералов даты. В частности, эта библиотека предназначена для обнаружения этих типов ошибок во время компиляции. Кроме того, operator-() не используется для этой цели, потому что это может слишком легко привести к ошибкам во время выполнения при кодировании арифметики даты. operator/() имеет правильный приоритет и синтаксис, чтобы избежать таких ошибок. - person Howard Hinnant; 30.07.2015
comment
Кроме того, синтаксис y/m/d является необязательным. Существует традиционный безопасный синтаксис конструктора, если вы хотите его использовать... все описано на howardhinnant. github.io/date_v2.html . - person Howard Hinnant; 30.07.2015
comment
@HowardHinnant: Вау, да, я хорошо осведомлен о международных различиях в обозначениях дат, спасибо. Под нами я имел в виду всех здравомыслящих программистов, с которыми я говорил по этому поводу в прошлом. :) - person Lightness Races in Orbit; 30.07.2015
comment
@LightnessRacesinOrbit: Хорошо. Пожалуйста, не стесняйтесь загружать date.h по адресу github.com/HowardHinnant/date/blob. /master/date.h и запустите его через соответствующий компилятор C++11 или C++14. Если вы найдете способ создать дату, которая, по вашему мнению, подвержена ошибкам (т. е. ошибка программиста, которую компилятор должен обнаружить во время компиляции, но не делает этого), просто дайте мне знать, и я посмотрю, что я могу с этим сделать. - person Howard Hinnant; 30.07.2015
comment
@HowardHinnant: Эм, я никогда не утверждал, что вы можете сделать с ним программу, которая не будет делать то, что вы написали. Я даже сказал, что однозначно в таком виде, да. Я говорю о человеческом аспекте здесь. - person Lightness Races in Orbit; 30.07.2015
comment
Также я только что заметил, что это ваша библиотека, а не Boost или stdlib. Не хотел позиционировать свои взгляды как нападение. - person Lightness Races in Orbit; 30.07.2015
comment
Понял, без проблем. Я нахожусь в режиме сбора отзывов и конструктивной критики, чтобы сделать библиотеку более надежной. Так что стреляйте в него пулями. Это нуждается в тестировании. :-) - person Howard Hinnant; 30.07.2015