Я использую tm / mktime неправильно, и если нет, то обходной путь?

Я думаю, что следующая программа должна выводить секунды до 1970 года в первый день каждого года с 1 до 1970 года, которому предшествует размер time_t в системе, на которой он скомпилирован ( CHAR_BIT – это макрос, поэтому я думаю, что вы не можете просто скопировать скомпилированный исполняемый файл и предполагающий его правильность, хотя на практике все использует 8-битный char эти дни).

 #include  #include  #include  #include  #include  void do_time(int year) { time_t utc; struct tm tp; memset(&tp, 0, sizeof(tp)); tp.tm_sec = 0; tp.tm_min = 0; tp.tm_hour = 0; tp.tm_mday = 1; tp.tm_mon = 0; tp.tm_year = year - 1900; tp.tm_wday = 1; tp.tm_yday = 0; tp.tm_isdst = -1; printf("%d %ld\n",year, mktime(&tp)); } int main(){ printf("time_t is %lu bits\n",sizeof(time_t)*CHAR_BIT); for (int i = 1; i<1971; i++) do_time(i); exit(0); } 

Однако в OS X (10.11.3 15D21) это работает только в течение лет> = 1902, несмотря на то, что time_t составляет 64 бит. Я мог бы понять, были ли программисты в Apple ленивыми и не поддерживали каких-либо лет до 1970 года, но правильное поведение, начатое в 1902 году, а затем прекращение выглядит скорее как ошибка с моей стороны.

Консультирование по стандарту C:

Диапазон и точность времени, представляемого в clock_t и time_t определяются реализацией. [..]

[N1570 §7.27.1 / 4] (акцент мой)

И далее, относительно mktime :

Функция mktime возвращает указанное время календаря в виде значения типа time_t . Если календарное время не может быть представлено, функция возвращает значение (time_t)(-1) .

[N1570 §7.27.2.3 / 3]

Таким образом, если возвращаемое значение mktime равно (time_t)(-1) за годы, когда оно не работает … вы сами по себе.


На самом деле, IMO, стандарт немного тихий обо всем этом:

[..] int tm_year; // years since 1900 int tm_year; // years since 1900 [..]

[N1570 §7.27.1 / 4]

Это может означать (положительные) годы с 1900 года, но тогда зачем использовать целое число со знаком.


В качестве примечания: в моей системе (Linux 3.14.40 x86_64 glibc-2.21) я получаю …

 time_t is 64 bits 1 -62135600008 ... 1969 -31539600 1970 -3600 

Рассмотрение работы вокруг части: вы можете, конечно, взглянуть на реализации libc, которые делают то, что вы хотите, и пытаетесь использовать их код (если это возможно в отношении любых лицензий, которые вам нужно соблюдать). Вот тот, который использует моя система.

В ОС UNIX часто используются версии временных функций с поддержкой 64 бит. OS X может иметь что-то подобное, хотя я не мог найти его с помощью моего быстрого поиска. Для получения дополнительной информации см. 64-битное временное преобразование unix .

EDIT: Я нашел Mac, чтобы проверить это, и, похоже, у него нет функции mktime64. Я нашел эту библиотеку, которая могла бы работать как работа, хотя я не проверял ее лично.