c++unix-timestamptime-tboost-date-timetimeval

Get time_t / timeval corresponding to ( local_timezone ) midnight on a given date


Given a time_t or struct timeval, how do I get the timeval or time_t of midnight EST/EDT ( local timezone ) on that day ? As in assuming local timezone is EST/EDT, given a time_t corresponding to say 2010-11-30 08:00:00 EST/EDT, the expected answer is a time_t that corresponds to 2010-11-30 00:00:00 EST/EDT

Attempt 1 ( Incorrect: since it does not handle DST, and assumes EST/EDT is always 5 hours behind UTC ):

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

Attempt 2 ( Incorrect: since it returns a time_t that corresponds to when it was midnight UTC and not EST/EDT, local timezone ):

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_ );
}

I feel there should be a solution involving (i) struct tm, mktime or (ii) boost::local_date_time perhaps ?


Solution

  • Current solution :

    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_ ) ) ;
    }
    

    Please advise.