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ąDateTimemakeUtcTime 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ń)

questionAnswers(2)

yourAnswerToTheQuestion