[英]How to Convert “struct tm” (VTYPE_TM) to DATE(double) - Native API?
我正在使用本机 API技术在本机 C++(Visual Studio 2013 版)中编写一个小型 DLL。
从我的 DLL 内部的外部程序中,我得到日期(没有时间:只有日、月、年)作为VTYPE_TM类型的变量(这是"struct tm" )。
if (paParams[0].vt == VTYPE_TM)
double dateFrom = (double)paParams[0].tmVal ; // convert error - but how ?
接下来,我需要将包含在tm结构中的这个日期转换为DATE(double)类型。
有关DATE(double)的更多信息可以在这里找到 - 在在线计算器https://planetcalc.com/7027/中。
现在是实际问题和我的问题:如何将"struct tm"转换为DATE(double) ?
据我了解,我们需要编写一个 function 将每个字段值从 tm 结构转换为所需的双精度。 但是没有现成的解决方案吗? 也许我需要使用一些中间类型,但我不知道是哪一种。
你能告诉我如何实现这个吗?
铁杆 C ++ 编程大师的问题!
这可以使用 C++20 <chrono>
轻松完成。 不幸的是,这部分 C++20 尚未发布,但供应商正忙于实施它。
幸运的是,对于 C++20 的这一部分,存在一个免费的、开源的、仅包含标头的预览版,它适用于 C++11/14/17。 此外,预览版有一个示例页面,其中已经解决了这个问题作为示例。
这是转换为仅使用double
类型来回转换的示例,包括您链接到的文档页面中的所有测试用例。
#include "date/date.h"
#include <ctime>
#include <iostream>
template <class D>
date::sys_time<D>
to_sys_time(double dt)
{
using namespace date;
using namespace std::chrono;
using fdays = duration<double, days::period>;
using ftime = time_point<system_clock, fdays>;
auto ft = ftime{fdays{dt}};
if (ft < ftime{})
{
auto d = time_point_cast<days>(ft);
auto t = d - ft;
ft = d + t;
}
ft -= sys_days{1970_y/January/1} - sys_days{1899_y/December/30};
return round<D>(ft);
}
template <class D>
double
to_double(date::sys_time<D> tp)
{
using namespace date;
using namespace std::chrono;
using fdays = duration<double, days::period>;
using ftime = time_point<system_clock, fdays>;
auto ft = ftime{tp} + (sys_days{1970_y/January/1} - sys_days{1899_y/December/30});
if (ft >= ftime{})
return ft.time_since_epoch().count();
auto d = floor<days>(ft);
auto t = d - ft;
return (d + t).time_since_epoch().count();
}
void
test(double d)
{
using namespace std;
using namespace std::chrono;
using namespace date;
auto t = to_sys_time<seconds>(d);
auto d2 = to_double(t);
cout << d << " is " << t << " which is " << d2 << '\n';
}
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
test(-1.25);
test(-1.3);
test(-0.5);
test(0.5);
year_month_day today = floor<days>(system_clock::now());
std::tm tm{};
tm.tm_year = int{today.year()} - 1900;
tm.tm_mon = unsigned{today.month()} - 1;
tm.tm_mday = unsigned{today.day()};
sys_days sd = year{tm.tm_year + 1900}/(tm.tm_mon + 1)/tm.tm_mday;
cout << "Today " << today << " is " << to_double(sd) << '\n';
}
这当前输出:
-1.25 is 1899-12-29 06:00:00 which is -1.25
-1.3 is 1899-12-29 07:12:00 which is -1.3
-0.5 is 1899-12-30 12:00:00 which is 0.5
0.5 is 1899-12-30 12:00:00 which is 0.5
Today 2021-01-30 is 44226
前四行只是确认转换函数根据您的文档产生正确的值。
最后,当前日期(UTC)从system_clock::now()
获得,转换为std::tm
,然后转换回天精度chrono::time_point
(基于system_clock
)。 然后将此time_point
输入to_double
以将其转换为 double,目前结果为 44226。
考虑到文档最后一段中描述的这种格式的奇异历史,这些转换函数是不必要的复杂。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.