Standardowy zgodny sposób konwertowania std :: time_t na System :: DateTime?
Znalazłem już kilka odpowiedzi związanych z konwersjąstd::time_t
wartość doSystem::DateTime
i z powrotem. Jednak prawie wszystkie odpowiedzi wydają się pomijać ten typstd::time_t
jest właściwie niezdefiniowany w standardzie. Większość rozwiązań po prostu rzucastd::time_t
do wszystkiego, co potrzebne, lub zastosować operacje arytmetyczne dostd::time_t
obiekt, który jest możliwy, ponieważ jest to typ arytmetyczny, ale nie ma specyfikacji co do wyniku takiej operacji. wiem towiększość kompilatory definiujątime_t
jakoint
pewnej wielkości, ale sam fakt, że się zmieniłint32
doint64
w wielu wdrożeniach ostatnio pokazuje, że zmiany są rzeczywiście możliwe.
Więc wymyśliłem to rozwiązaniepowinien pracować z dowolnym rodzajemstd::time_t
. Działa z tego, co widziałem. Ale zastanawiałem się -Czy są jakieś możliwe pułapki, o których mógłbym nie wiedzieć?
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)
Dokonano 3 założeń:
Wynikłystd::time_t
powinien być w UTC, ponieważ nie zawiera żadnych informacji o lokalizacjiWynikłySystem::DateTime
powinien być czasem lokalnymSystem::DateTime::Now
zwraca zlokalizowanąDateTime
makeUtcTime
jest funkcją pomocniczą tworzącąstd::tm
z podanych wartości i tworzy UTCstd::time_t
z tego. Jest to obecnie realizowane za pomocą_mkgmtime
ponieważ nasz kod interop może bezpiecznie polegać na istnieniu rozszerzeń Microsoft. Jednak wersja UTCmktime
jest również dostępny w innych kompilatorach (standardmktime
oczekuje czasu lokalnego).2 mniej ważne rzeczy do rozważenia:
Theconst_cast
jest konieczne, ponieważ szablon marshal_as oczekuje aconst T&
jako parametr i nie mogę uzyskać dostępu do właściwości obiektu typu wartości .NET. Jednak może być lepsze rozwiązanie.Powinienunix_epoch...
byćstatic const
?(Nie byłem pewien, czy powinno to być opublikowane na „Programm Exchange”, ponieważ jest to bardziej dyskusja, ale ponieważ jest to bardzo specyficzne pytanie C ++, pomyślałem, że SO może być lepszym miejscem do zadawania pytań)