Ошибка 2038 года

Так как time_t может представлять интервалы времени длиной в 68 лет, а многие реализации для представления текущего времени в качестве начала отсчета используют 1970 год, в большинстве популярных реализаций C++ невозможно представлять даты и времена после 2038 года. Это означает, что если программисты не предпримут мер предосторожности, то в 2038 году большая часть программного обеспечения перестанет работать.

Наиболее удобное представление текущих даты и времени можно получить, преобразовав их с помощью функций localtime или gmtime в структуру tm. Структура tm содержит целочисленные поля, показанные в примере 5.2.

Пример 5.2. Содержимое структуры tm

struct tm {

 int tm_sec;   // секунды в минуте от 0 до 61 (60 и 61 для секунд координации)

 int tm_min;   // минуты в часе от 0 до 59

 int tm_hour;  // часы в сутках от 0 до 23

 int tm_mday;  // день месяца от 0 до 31

 int tm_mon;   // месяц года от 0 до 11

 int tm_year;  // год после 1900

 int tm_wday;  // дней после воскресенья

 int tm_yday;  // дней после 1-го января

 int tm_isdst; // часы летнего времени

};

При использовании функции gmtime не забудьте проверить ее возвращаемое значение. Если компьютер, на котором выполняется код, не имеет определенной локальной временной зоны (часового пояса), функция gmtime не сможет вычислить время UTC и вернет 0. Если передать 0 в функцию asctime, то результатом будет неопределенное поведение.

Функции localtime, gmtime и asctime возвращают указатели на статически размещенные в памяти объекты. Это более эффективно для библиотеки, не означает, что последующие вызовы будут изменять значение этих объектов. Код в примере 5.3 показывает, как это может привести к неожиданным эффектам.

Пример 5.3. Подводные камни использования asctime

void f() {

 char* x = asctime(localtime(time(0)));

 wait_for_15_seconds(); // выполняет длительную задачу обработки

 asctime(localtime(time(0)));

 cout << x << endl; // печатает текущее время, а не то что 15 секунд назад.

}

<p>5.2. Форматирование даты/времени в виде строки</p>Проблема

Требуется преобразовать дату и/или время в строковый формат

Решение

Используйте шаблон класса time_put из заголовочного файла , как показано в примере 5.4.

Пример 5.4. Форматирование строки даты/времени

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

ostream& formatDateTime(ostream& out, const tm& t, const char* fmt) {

 const time_put& dateWriter = use_facet >(out.getloc());

 int n = strlen(fmt);

 if (dateWriter.put(out, out, ' ', &t, fmt, fmt + n).failed()) {

  throw runtime_error("невозможно отформатировать дату и время");

 }

 return out;

}

string dateTimeToString(const tm& t, const char* format) {

 stringstream s;

 formatDateTime(s, t.format);

 return s.str();

}

tm now() {

 time_t now = time(0);

 return *localtime(&now);

}

int main() {

 try {

  string s = dateTimeToString(now(), "%A %B, %d %Y %I:%M%p");

  cout << s << endl;

  s = dateTimeToString(now(), "%Y-%m-%d %H:%M:%S);

  cout << s << endl;

 } catch(...) {

  cerr << "невозможно отформатировать дату и время" << endl;

Перейти на страницу:

Похожие книги