我已经找到了几个与将std::time_t
值相互转换相关的答案System::DateTime
。但是,几乎所有答案似乎都忽略std::time_t
了标准中实际上未定义的类型。大多数解决方案只是强制std::time_t
转换为任何需要的对象或将算术运算应用于std::time_t
可能的对象,因为它是算术类型,但没有关于此类运算结果的规范。我知道大多数编译器都定义time_t
为int
某种大小的 an,但仅在最近的许多实现中它已从 更改为 的事实int32
表明int64
,更改确实是可能的。
所以我想出了这个解决方案,它应该适用于任何类型的std::time_t
. 它从我所看到的工作。但我想知道 -有没有我可能不知道的陷阱?
template <>
inline System::DateTime marshal_as(const std::time_t &from_object)
{
// Returns DateTime in Local time format from time_t (assumed to be UTC)
const auto unix_epoch = makeUtcTime(1970, 1, 1, 0, 0, 0);
const auto unix_epoch_dt = System::DateTime(1970, 1, 1, 0, 0, 0, System::DateTimeKind::Utc);
const auto secondsSinceEpoch = std::difftime(from_object, unix_epoch);
return const_cast<System::DateTime&>(unix_epoch_dt).AddSeconds(secondsSinceEpoch).ToLocalTime();
} // end of System::DateTime marshal_as(const std::time_t &from_object)
template <>
inline std::time_t marshal_as(const System::DateTime &from_object)
{
// Returns time_t in UTC format from DateTime
auto from_dt = const_cast<System::DateTime&>(from_object).ToUniversalTime();
return makeUtcTime(from_dt.Year, from_dt.Month, from_dt.Day, from_dt.Hour, from_dt.Minute, from_dt.Second);
} // end of std::time_t marshal_as(const System::DateTime &from_object)
做了3个假设:
- 结果
std::time_t
应该是UTC,因为它不包含任何本地化信息 - 结果
System::DateTime
应该是本地时间,因为System::DateTime::Now
返回一个本地化的DateTime
makeUtcTime
是一个辅助函数std::tm
,根据提供的值创建一个并从中创建一个 UTCstd::time_t
。这目前是使用实现的,_mkgmtime
因为我们的互操作代码可以安全地依赖于 Microsoft 扩展的存在。但是,UTC 版本mktime
在其他编译器中也很容易获得(标准mktime
需要本地时间)。
2个不太重要的事情要考虑:
- 这
const_cast
是必要的,因为 marshal_as-template 需要一个const T&
as 参数,而我无法访问 const .NET 值类型对象的属性。但是,可能有更好的解决方案。 unix_epoch...
东西应该是吗static const
?
(我不确定这是否应该发布在“程序员交流”上,因为它更像是一个讨论,但由于这是一个非常具体的 C++ 问题,我认为 SO 可能是更好的提问场所)