mktime обрабатывает только високосные годы на Clang?

В этом ответе я предложил marihikari использовать стандартную функциональность mktime вместо того, чтобы пытаться ввести собственную систему григорианского календаря.

Я написал эту функцию, чтобы продемонстрировать, как можно использовать mktime для достижения этой цели:

bool leap_year(int year) {
    tm bar = { 0, 0, 0, 29, 1, year - 1900 };

    mktime(&bar);

    return bar.tm_mday == 29 && bar.tm_mon == 1 && bar.tm_year == year - 1900;
}

Тестирование с помощью:

cout << "2000: " << leap_year(2000) << "\n2001: " << leap_year(2001) << "\n2004: " << leap_year(2004) << "\n1900: " << leap_year(1900) << "\n2100: " << leap_year(2100) << endl;

Дал правильный результат в Clang 3.7.0:

2000: 1
2001: 0
2004: 1
1900: 0
2100: 0

Но неверный результат в gcc 5.1.0:

2000: 1
2001: 0
2004: 1
1900: 1
2100: 1

И неверный результат в Visual Studio 2015:

2000: 1
2001: 0
2004: 1
1900: 1
2100: 0

Я предполагаю, что это ошибка в gcc 5.1.0 и Visual Studio 2015?


person Jonathan Mee    schedule 02.11.2015    source источник


Ответы (1)


mktime:

Преобразует местное календарное время во время, начиная с эпохи, как объект time_t. time->tm_wday и time->tm_yday игнорируются. Значения во времени могут быть за пределами своих нормальных диапазонов.
...
Если преобразование прошло успешно, объект времени изменяется. Все поля времени обновляются, чтобы соответствовать их надлежащему диапазону.

mktime вернет:

Время с эпохи как объект time_t в случае успеха или -1, если время не может быть представлено как объект time_t.

Однако не указано, какие усилия должна предпринять реализация, чтобы преобразовать tm. Таким образом, пока время конвертируется или static_cast<time_t>(-1), требования для mktime выполняются.

Это означает, что следующая функция будет работать на всех платформах, которые корректно поддерживают mktime:

bool leap_year(int year) {
    tm bar = { 0, 0, 0, 29, 1, year - 1900 };

    return static_cast<time_t>(-1) != mktime(&bar) && bar.tm_mday == 29 && bar.tm_mon == 1 && bar.tm_year == year - 1900;
}
person Jonathan Mee    schedule 02.11.2015