.net - Standard conformant way of converting std::time_t to System::DateTime? -
i have found several answers related converting std::time_t
value system::datetime
, back. however, answers seem neglect type of std::time_t
undefined in standard. solutions cast std::time_t
whatever needed or apply arithmetic operations std::time_t
object possible since it's arithmetic type, there no specification result of such operation. know most compilers define time_t
int
of size fact alone has changed int32
int64
in many implementations shows changes indeed possible.
so i've come solution should work type of std::time_t
. works have seen. wondering - are there possible pitfalls might unaware of?
template <> inline system::datetime marshal_as(const std::time_t &from_object) { // returns datetime in local time format time_t (assumed 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 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 assumptions made:
- resulting
std::time_t
should in utc since doesn't contain info on localization - resulting
system::datetime
should local time sincesystem::datetime::now
returns localizeddatetime
makeutctime
helper function creatingstd::tm
values supplied , creates utcstd::time_t
out of it. implemented using_mkgmtime
because our interop code can safely rely on existence of microsoft extensions. however, utc version ofmktime
readily available in other compilers (standardmktime
expects local time).
2 less important things consider:
- the
const_cast
necessary because marshal_as-template expectsconst t&
parameter , can't access properties of const .net value-type object. there might better solution. - should
unix_epoch...
stuffstatic const
?
(i wasn't sure if should posted on "programmers exchange" since it's more of discussion since it's specific c++ question thought might better place ask)
it isn't productive insist on "standard conformant" way make conversion. place std::time_t , system::datetime ever going meet covered ecma-372 standard. of there right now, , surely ever be, one implementation. mono project assumed source of one, right appear entirely uninterested in providing mixed-mode implementation, reason you'd ever consider using c++/cli.
std::time_t steadily marching towards y2k38 disaster. microsoft pre-emptively having done it, , having because went llp64, else counting on lp64 data model keeping them out of trouble. in other words, no remaining 32-bit processors still running in 2038. self-fulfilling prophesy.
regardless, conversion going have work elapsed milliseconds since 1/1/1970. , can 32-bit or 64-bit integral value, depending on implementation. system::datetime, working milliseconds requires using double. , compiler going able convert between double , integral value, standard conversion in curly brace languages. conversion has millisecond accuracy way datetime::maxvalue. 1 furthermore guaranteed round-trip. not going have problem ever porting code, @ least until 2038:
#include <ctime> using namespace system; public ref class conversions { public: static datetime time_t2datetime(std::time_t date) { double msec = static_cast<double>(date); return datetime(1970, 1, 1, 0, 0, 0, datetimekind::utc).addmilliseconds(msec); } static std::time_t datetime2time_t(datetime date) { timespan diff = date.touniversaltime() - datetime(1970, 1, 1); return static_cast<std::time_t>(diff.totalmilliseconds); } };
Comments
Post a Comment