如何从 std::tm 转换为 Windows::Foundation::DateTime
How to convert from std::tm to Windows::Foundation::DateTime
我正在尝试在 Windows 运行时组件中将 std::tm
转换为 Windows::Foundation::DateTime
。
Windows::Foundation::DateTime
中唯一的属性是UniversalTime
,定义为:
A 64-bit signed integer represents a point in time as the number of 100-nanosecond interval prior to or after midnight on January 1, 1601 (according to Gregorian Calendar)
有没有办法在 std
中获取此值?还是有一种标准的方法来进行转换?
您可以使用 mktime
将时间转换为 unix,
然后添加幻数 116444736000000000ULL
:
/* shift is difference between 1970-Jan-01 & 1601-Jan-01
* in 100-nanosecond intervals */
const uint64_t shift = 116444736000000000ULL; // (27111902 << 32) + 3577643008
来自 boost/date_time/filetime_functions.hpp
这是另一种派生此常量的方法,但需要此 date library 序列化两个公历日期:
#include "date.h"
int
main()
{
using namespace std::chrono;
using namespace date;
using namespace std;
using wticks = ratio_multiply<nano, ratio<100>>;
constexpr duration<int64_t, wticks> t =
sys_days{jan/1/1970} - sys_days{jan/1/1601};
static_assert(t.count() == 116444736000000000, "");
}
这需要C++14在编译时完成。在 C++11 中,这可以在 运行 时间完成(即你不能将 t
声明为 constexpr
或在 C++11 中的 static_assert
中使用它). date library 已移植到 VS-2015,但 constexpr
目前在该平台上被禁用。
更新
这是将本地 tm
转换为自 1601 年 1 月 1 日以来以 100 纳秒为单位的数字的代码。要计算出计算机的本地时区,需要此 timezone library。
#include "date.h"
#include "tz.h"
#include <iostream>
#include <thread>
int
main()
{
using namespace std::chrono;
using namespace date;
using namespace std;
// Concurrently initialize timezone database (as an optimization)
thread{get_tzdb}.detach();
// get an example local tm
auto now = time(nullptr);
struct tm tm = *localtime(&now);
// convert tm into a local time_point
auto local_tp = local_days{year{tm.tm_year+1900}/(tm.tm_mon+1)/tm.tm_mday}
+ hours{tm.tm_hour} + minutes{tm.tm_min} + seconds{tm.tm_sec};
// convert local time_point to UTC time_point
auto tp = current_zone()->to_sys(local_tp);
// Create handy types for dealing with 100-nanosecond units
using wperiod = ratio_multiply<nano, ratio<100>>;
using wticks = duration<int64_t, wperiod>;
// Get number of 100-nanosecond intervals since Jan 1, 1601 00:00:00 UTC
auto t = wticks{tp - sys_days{jan/1/1601}};
cout << t.count() << '\n';
}
这只是为我输出:
130925235970000000
我正在尝试在 Windows 运行时组件中将 std::tm
转换为 Windows::Foundation::DateTime
。
Windows::Foundation::DateTime
中唯一的属性是UniversalTime
,定义为:
A 64-bit signed integer represents a point in time as the number of 100-nanosecond interval prior to or after midnight on January 1, 1601 (according to Gregorian Calendar)
有没有办法在 std
中获取此值?还是有一种标准的方法来进行转换?
您可以使用 mktime
将时间转换为 unix,
然后添加幻数 116444736000000000ULL
:
/* shift is difference between 1970-Jan-01 & 1601-Jan-01
* in 100-nanosecond intervals */
const uint64_t shift = 116444736000000000ULL; // (27111902 << 32) + 3577643008
来自 boost/date_time/filetime_functions.hpp
这是另一种派生此常量的方法,但需要此 date library 序列化两个公历日期:
#include "date.h"
int
main()
{
using namespace std::chrono;
using namespace date;
using namespace std;
using wticks = ratio_multiply<nano, ratio<100>>;
constexpr duration<int64_t, wticks> t =
sys_days{jan/1/1970} - sys_days{jan/1/1601};
static_assert(t.count() == 116444736000000000, "");
}
这需要C++14在编译时完成。在 C++11 中,这可以在 运行 时间完成(即你不能将 t
声明为 constexpr
或在 C++11 中的 static_assert
中使用它). date library 已移植到 VS-2015,但 constexpr
目前在该平台上被禁用。
更新
这是将本地 tm
转换为自 1601 年 1 月 1 日以来以 100 纳秒为单位的数字的代码。要计算出计算机的本地时区,需要此 timezone library。
#include "date.h"
#include "tz.h"
#include <iostream>
#include <thread>
int
main()
{
using namespace std::chrono;
using namespace date;
using namespace std;
// Concurrently initialize timezone database (as an optimization)
thread{get_tzdb}.detach();
// get an example local tm
auto now = time(nullptr);
struct tm tm = *localtime(&now);
// convert tm into a local time_point
auto local_tp = local_days{year{tm.tm_year+1900}/(tm.tm_mon+1)/tm.tm_mday}
+ hours{tm.tm_hour} + minutes{tm.tm_min} + seconds{tm.tm_sec};
// convert local time_point to UTC time_point
auto tp = current_zone()->to_sys(local_tp);
// Create handy types for dealing with 100-nanosecond units
using wperiod = ratio_multiply<nano, ratio<100>>;
using wticks = duration<int64_t, wperiod>;
// Get number of 100-nanosecond intervals since Jan 1, 1601 00:00:00 UTC
auto t = wticks{tp - sys_days{jan/1/1601}};
cout << t.count() << '\n';
}
这只是为我输出:
130925235970000000