Pregunta

Dado un TIME_T o Struct Timeval, ¿cómo obtengo el timeval o Time_T de la medianoche EST / EDT (TimeZone local) en ese día? Al asumir la zona horaria local es EST / EDT, dada un TIME_T que corresponde a decir 2010-11-30 08:00:00 EST / EDT, la respuesta esperada es un TIME_T que corresponde a 2010-11-30 00:00:00 EST/ EDT

intento 1 (incorrecto: Dado que no maneja DST, y asume EST / EDT siempre está 5 horas detrás de UTC):

time_t RewindToMidnight ( const time_t temp_time_t_ )
{
  return ( (5*3600) + ((( temp_time_t_ - 5*3600 )/86400 ) * 86400) );
}

Intento 2 (incorrecto: Dado que devuelve un TIME_T que corresponde cuando fue de la medianoche UTC y NO EST / EDT, TimeZone local):

time_t RewindToMidnight ( const time_t temp_time_t_ )
{
   boost::posix_time::ptime temp_ptime_ = boost::posix_time::from_time_t ( temp_time_t_ );
   boost::gregorian::date temp_date_ = temp_ptime_.date();
   boost::posix_time::ptime temp_ptime_midnight_ ( temp_date_,
                                                   boost::posix_time::time_duration ( 0, 0, 0 ) );
   return to_time_t ( temp_ptime_midnight_ );
}

time_t to_time_t ( const boost::posix_time::ptime & temp_ptime_ )
{
   boost::posix_time::ptime temp_epoch_ptime_(boost::gregorian::date(1970,1,1));
   boost::posix_time::time_duration::sec_type temp_sec_type_ = ( temp_ptime_ - temp_epoch_ptime_ ).total_seconds();
   return time_t ( temp_sec_type_ );
}

Siento que debería haber una solución que involucre (i) struct tm, mktime o (ii) Boost :: local_date_time quizás?

¿Fue útil?

Solución 3

Solución actual:

time_t RewindToMidnight ( const time_t & temp_time_t_ )
{
    int temp_yyyymmdd_ = iso_date_from_time_t ( temp_time_t_ );
    return time_t_from_iso_date ( temp_yyyymmdd_ );
}

int iso_date_from_time_t ( const time_t & in_time_t_ ) 
{
     tm temp_this_tm_;

     { // the following to set local dst fields of struct tm ?
         time_t tvsec_ = time(NULL);
         localtime_r ( & tvsec_, & temp_this_tm_ ) ;
     }
     localtime_r ( & in_time_t, & temp_this_tm_ ) ;

     return ( ( ( ( 1900 + temp_this_tm_.tm_year ) * 100 + ( 1 + temp_this_tm_.tm_mon ) ) * 100 ) + temp_this_tm_.tm_mday ) ;
}

time_t time_t_from_iso_date ( const int & temp_yyyymmdd_ ) 
{ 

     boost::gregorian::date d1 ( (int)( temp_yyyymmdd_/10000), 
                                 (int)( ( temp_yyyymmdd_/100) % 100), 
                                 (int)( temp_yyyymmdd_ % 100) );

     std::tm this_tm_ = to_tm ( d1 );
     return ( mktime ( & this_tm_ ) ) ;
}

Por favor avise.

Otros consejos

Como Time_T es el tiempo en segundos desde la época (00:00:00 UTC, 1 de enero de 1970), solo necesita deshacerse de los segundos del día.Hay 86400 segundos en un día (normalmente los segundos del salto se ignoran), por lo que el resultado debe ser un múltiplo de 86400. Por lo tanto:

time_t now = time();
time_t midnight = now / 86400 * 86400

time_t local_midnight(time_t x) {
  struct tm t;
  localtime_r(&x, &t);
  t.tm_sec = t.tm_min = t.tm_hour = 0;
  return mktime(&t);
}

Utilicé localtime_r, ya que debe estar disponible, ya que también lo usó en su respuesta.

ejemplo :

int main() {
  time_t now = time(0);
  cout << "local: " << asctime(localtime(&now));
  cout << "UTC:   " << asctime(gmtime(&now));
  time_t midnight = local_midnight(now);
  cout << "\n       " << asctime(localtime(&midnight));
  return 0;
}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top