Получить time_t/timeval, соответствующий (local_timezone) полуночи заданной даты

Учитывая time_t или struct timeval, как мне получить timeval или time_t полуночи EST/EDT (местный часовой пояс) в этот день? Поскольку предполагается, что местный часовой пояс — EST/EDT, учитывая time_t, соответствующий, скажем, 2010-11-30 08:00:00 EST/EDT, ожидаемый ответ — time_t, соответствующий 2010-11-30 00:00:00 EST. /ЛЕТНЕЕ СЕВЕРОАМЕРИКАНСКОЕ ВОСТОЧНОЕ ВРЕМЯ

Попытка 1 (неправильно: поскольку он не обрабатывает летнее время и предполагает, что EST/EDT всегда на 5 часов отстает от UTC):

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

Попытка 2 (неправильно: так как он возвращает time_t, который соответствует полуночи UTC, а не EST/EDT, местный часовой пояс):

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) struct tm, mktime или (ii) boost::local_date_time, возможно?


person Humble Debugger    schedule 05.02.2011    source источник
comment
Ваше time_t в UTC или по местному времени?   -  person MerickOWA    schedule 06.02.2011
comment
Данный time_t находится в местном часовом поясе, который является EST.   -  person Humble Debugger    schedule 06.02.2011
comment
EST отстает от UTC на 5 часов. EDT — часовой пояс летнего времени.   -  person Fred Nurk    schedule 08.02.2011


Ответы (3)


Поскольку time_t — это время в секундах с начала Эпохи (00:00:00 UTC, 1 января 1970 г.), вам просто нужно избавиться от секунд дня. В сутках 86400 секунд (секунды координации обычно игнорируются), поэтому результат должен быть кратен 86400. Отсюда:

time_t now = time();
time_t midnight = now / 86400 * 86400
person Maxim Egorushkin    schedule 05.02.2011
comment
Необходимый ответ — это time_t, соответствующий полуночи EST. Функция, написанная в вопросе, хотя и неэффективна, на самом деле возвращает time_t, соответствующую полуночи UTC. - person Humble Debugger; 06.02.2011
comment
В приложениях, которые управляют временем в разных часовых поясах, лучше всего кодировать ваше приложение для работы во времени UTC. Преобразование в/из местных часовых поясов только при вводе/выводе. Таким образом, вам не нужно носить с собой часовой пояс вместе со значением времени в остальной части вашего кода. - person Maxim Egorushkin; 06.02.2011
comment
К сожалению, большая часть финансового мира устанавливает часы на EST/CST. - person Humble Debugger; 06.02.2011
comment
Две последние крупномасштабные электронные торговые системы, над которыми я работал, используют только время UTC. Если торговой системе необходимо торговать на биржах по всему миру, установка системных часов на что-то другое, кроме UTC, вызывает много проблем. Тем не менее, вы правы в том, что исходный вопрос требует ответа не во времени UTC. Существуют способы конвертировать текущее время UTC в местное время и обратно, и вы можете сделать это относительно просто с помощью Boost. - person Maxim Egorushkin; 06.02.2011
comment
@MaximYegorushkin Последую твоему совету и постараюсь перевести все на UTC. Однако это потребует некоторой нетехнической борьбы :) Вы упомянули, что существуют способы конвертировать текущее время UTC в местное время и обратно, и вы можете сделать это относительно просто с помощью Boost. любые указатели? - person Humble Debugger; 06.02.2011
comment
boost.org/doc/ libs/1_45_0/doc/html/дата_время/ - person Maxim Egorushkin; 07.02.2011

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

Я использовал localtime_r, поскольку он должен быть доступен, поскольку вы также использовали его в своем ответе.

Пример:

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;
}
person Fred Nurk    schedule 08.02.2011

Текущее решение:

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

Пожалуйста, порекомендуйте.

person Humble Debugger    schedule 06.02.2011