Forma estándar de convertir std :: time_t a System :: DateTime?
Ya he encontrado varias respuestas relacionadas con la conversión de unstd::time_t
valor paraSystem::DateTime
y de vuelta. Sin embargo, casi todas las respuestas parecen descuidar que el tipo destd::time_t
En realidad es indefinido en la norma. La mayoría de las soluciones acaba de lanzarstd::time_t
a lo que sea necesario o aplicar operaciones aritméticas a unastd::time_t
Objeto que es posible ya que es un tipo aritmético, pero no hay ninguna especificación sobre el resultado de dicha operación. Yo sé esomás los compiladores definentime_t
como unint
de algún tamaño, pero solo el hecho de que ha cambiado desdeint32
aint64
En muchas implementaciones, recientemente se ha demostrado que los cambios son posibles.
Así que he venido con esta solución quedebería Trabajar con cualquier tipo destd::time_t
. Funciona a partir de lo que he visto. Pero me preguntaba ...¿Hay algún error posible que pueda ignorar?
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)
Se hicieron 3 suposiciones:
Resultantestd::time_t
debería estar en UTC ya que no contiene ninguna información sobre la localizaciónResultanteSystem::DateTime
debe ser hora local desdeSystem::DateTime::Now
devuelve un localizadoDateTime
makeUtcTime
es una función auxiliar que crea unastd::tm
A partir de los valores suministrados y crea un UTC.std::time_t
fuera de el. Esto se implementa actualmente utilizando_mkgmtime
porque nuestro código de interoperabilidad puede confiar en la existencia de extensiones de Microsoft. Sin embargo, una versión UTC demktime
también está disponible en otros compiladores (estándarmktime
espera hora local).2 cosas menos importantes a tener en cuenta:
losconst_cast
es necesario porque la plantilla marshal_as espera unaconst T&
como parámetro y no puedo acceder a las propiedades de un objeto de tipo de valor .NET const. Sin embargo, podría haber una mejor solución.Si elunix_epoch...
cosas seanstatic const
?(No estaba seguro de si esto debería publicarse en "Intercambio de programadores" ya que es más una discusión, pero como es una pregunta muy específica en C ++, pensé que SO podría ser el mejor lugar para preguntar)