Я уже нашел несколько ответов, связанных с преобразованием значения std::time_t
в System::DateTime
и обратно. Тем не менее, почти все ответы, похоже, не учитывают, что тип std::time_t
фактически не определен в стандарте. Большинство решений просто отличает std::time_t
к любым необходимым или применяемым арифметическим операциям к объекту std::time_t
, который возможен, поскольку он является арифметическим типом, но спецификация о результате такой операции отсутствует. Я знаю, что компиляторы определяют time_t
как int
определенного размера, но тот факт, что он изменился с int32
на int64
во многих реализациях, недавно показывает, что изменения действительно возможны.Стандартный способ конвертации std :: time_t в System :: DateTime?
Так что я придумал этот раствор, который должен работать с любым типом 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. Тем не менее, версия UTCmktime
также доступна в других компиляторах (стандартmktime
ожидает локальное время).
-менее важные вещи, чтобы рассмотреть следующие вопросы:
const_cast
необходим, потому что marshal_as-шаблон ожидаетconst T&
в качестве параметра, и я не могу получить доступ к свойствам объекта сопзИте .NET значения типа , Однако может быть лучшее решение.- Должно ли
unix_epoch...
материалаstatic const
?
(я не был уверен, что это должны быть размещены на «Программисты бирже», так как это больше обсуждения, но так как это очень специфический C вопрос ++ я думал, что SO может быть лучше спросить)
Есть два возможных определений time_t, в зависимости от того, определяется _USE_32BIT_TIME_T. Если он определен, он будет работать до тех пор, пока работает 32-бит time_t. System :: DateTime - 64 бит. – cup
Это правда, спасибо за информацию. Но так как полученное time_t во втором marshal_as построено с использованием календарных значений (Year, Month, ...), самое худшее, что может случиться, это то, что time_t возвращается как (time_t) (- 1), что в основном означает преобразование завершилось неудачно, потому что выбранная реализация time_t не может представлять DateTime. Но вот вы, причина № 1, почему просто преобразование TotalSeconds в time_t может потерпеть неудачу. – Excelcius
См. Здесь: http://stackoverflow.com/questions/9864339/boost-parse-date-time-string-and-yield-net-compatible-ticks-value – Ben