转换从公历开始到现在的天数

Convert days since start of the gregorian calender to date

我正在处理包含时间维度的 netCDF4 文件。此时间维度的值是双精度值,表示自 1582-10-15 00:00 以来的天数。为了允许用户与数据交互,我需要将这些时间戳转换为实际日期(如 01:01:2014T00:00:00)。

在研究这个问题时,我无法在 C++ 中找到解决方案。 netCDF Python 库提供了 num2date 和 date2num,它们正是我需要的。遗憾的是,我在 C++ 库中找不到这些函数。我将不胜感激有关如何执行此操作的任何建议。

int64_t nDays = int64_t(dtime); // Integral # days
dtime -= double(nDays);         // Fraction of a day
int64_t fSecs = int64_t(dtime * 86400.0 + 0.5); // Partial day in seconds
std::time_t nSecs = nDays * 86400LL + fSecs; // Number of secs since epoch
// Then use nSecs (after adjusting the epoch) to make a std::tm variable
nSecs -= 12219292800LL;// Subract # secs between 1582-10-15 and 1970-01-01
std::tm *pTM = std::gmtime(nSecs);
// and use std::strftime (or std::wcsftime) to format it into your string
wchar_t tStr[32];   wcsftime(tStr, 32, L"%Y-%m-%dT%H:%M:%S", pTM);

这很容易使用 Howard Hinnant's time/date library

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

date::sys_time<std::chrono::seconds>
to_time_point(double d)
{
    using namespace date;
    using namespace std::chrono;
    using ddays = duration<double, days::period>;
    return round<seconds>(ddays{d} + sys_days{1582_y/10/15});
}

int
main()
{
    using namespace date;
    std::cout << to_time_point(159562.572297) << '\n';
}

输出:

2019-08-27 13:44:06

你没有提到你想要的精度,但从你的示例输出来看,我推测是秒。您可以选择任何您想要的计时精度。该程序只是将您的 double 转换为周期为 days 的基于 double 的计时持续时间,然后将其添加到纪元中。结果是 chrono::system_clock::time_point,精度由您选择。虽然我建议您不要 使用nanosecondsnanoseconds 精度比 double 精度高 3 个数量级,sys_time<nanoseconds> 的范围是 [1677-09-21 00:12:43.145224192, 2262 -04-11 23:47:16.854775807]。而 sys_time<microseconds> 的范围是 +/-292 千年(很多)。

您可以使用同一个库将此 time_point 格式化为您想要的任何样式。例如:

std::cout << format("%d:%m:%YT%T", to_time_point(159562.572297)) << '\n';

输出:

27:08:2019T13:44:06

如果您在更新的标准可用后选择使用它,那么使用该库将非常好地迁移到 C++20。