Библиотека <chrono>
разработана таким образом, чтобы ошибка усечения не возникала неявно.Это связано с тем, что ошибка усечения может легко возникнуть и часто приводит к случайной потере информации.
Сообщение об ошибке:
не может быть преобразовано из time_point<steady_clock, duration<double,std::nano>>
в time_point<steady_clock, steady_clock::duration>
говорит, что неявное преобразование из дробных наносекунд (двойных) в целые наносекунды (целых) было предпринято, но не разрешено.Оказывается, что каждые steady_clock::duration
оказываются наносекундами, хотя это не указано.
Если вы хотите усечение (как в этом случае), можно использовать duration_cast
или time_point_cast
для усеченияк нулю.В C ++ 17 добавлены режимы усечения floor
, ceil
и round
.
Вот наиболее простой способ выполнения приведения усечения, который библиотека отказывается делать неявно:
#include <chrono>
typedef std::chrono::high_resolution_clock::time_point TimePoint;
typedef std::chrono::duration<double, std::ratio<86400>> JulianDays;
TimePoint JulianDaysToUTC(const JulianDays& days)
{
static const JulianDays EquivalentJulianYearInDays(2451545.0);
static const JulianDays LeapSecondCorrection(0.0008);
static const TimePoint CorrectedEpoch =
std::chrono::time_point_cast<TimePoint::duration>(
TimePoint() - EquivalentJulianYearInDays + LeapSecondCorrection);
return std::chrono::time_point_cast<TimePoint::duration>(CorrectedEpoch + days);
}
Первое приведение необходимо, потому что выражение TimePoint() - EquivalentJulianYearInDays + LeapSecondCorrection
имеет тип time_point<high_resolution_clock, duration<double, nano>>
(точка-точка наносекунды с плавающей точкой), а тип назначения - целая точка-наносекунды времени.То же самое для второго преобразования.
auto
может быть использовано, чтобы немного очистить этот код и избежать одного из преобразований:
#include <chrono>
typedef std::chrono::high_resolution_clock::time_point TimePoint;
typedef std::chrono::duration<double, std::ratio<86400>> JulianDays;
TimePoint JulianDaysToUTC(const JulianDays& days)
{
static const JulianDays EquivalentJulianYearInDays(2451545.0);
static const JulianDays LeapSecondCorrection(0.0008);
static const auto CorrectedEpoch = TimePoint() -
EquivalentJulianYearInDays + LeapSecondCorrection;
return std::chrono::time_point_cast<TimePoint::duration>(CorrectedEpoch + days);
}
Теперь CorrectedEpoch
является двойнымоснованный на наносекунде time_point, но эта деталь не очень важна для вашего алгоритма.
Кроме того, оправдан комментарий Николя Боласа о подозрительном использовании high_resolution_clock
.Ваш код может работать, если вы никогда не смешаете TimePoint
с high_resolution_clock::time_point
, полученным с high_resolution_clock::now()
.Однако вам будет безопаснее просто создать свои собственные часы с документированной эпохой 2000-01-01 12:00:00 UTC.Тогда любое случайное смешивание будет обнаружено во время компиляции.