tv_sec
содержит общее количество секунд с Unix Epoch - 1970-01-01 00:00:00 +00: 00 - и tv_usec
(или tv_nsec
при работе с более modern struct timespec
) содержит дробную часть - значения [0..999,999] микросекунд для struct timeval
и [0..999,999,999] наносекунд для struct timespec
.
В предыдущие дни 64-битные целые числа были Повсеместно, time_t
был 32-битным подписанным типом, и он «иссяк» в январе 2038 года - с начала эпохи прошло более 2 миллиардов секунд. Не было места для хранения подсекундных единиц в одном целом числе.
-2147483647 = 1901-12-13 20:45:53 +00:00
+2147483647 = 2038-01-19 03:14:07 +00:00
Даже сейчас, если вы имеете дело с наносекундами, вам нужно 30 бит для представления до 999 999 999 наносекунд (и 20 бит для представления до 999 999 микросекунд). Требования к наносекундам означают, что не имеет смысла пытаться масштабировать 64-битное число, чтобы представить секунды и наносекунды - проблема Y2K38 будет отложена примерно на 280 лет, тогда как решение, состоящее из двух частей, откладывает его до окончания вселенной , который должен быть достаточно длинным для всех. (Я планирую начать работать над проблемой Y10K на 5000-01-02, если я все еще рядом. ?)
Так что, хотя и не идеально, структура из двух частей позволяет легко использовать обычное форматирование функции, которые принимают значение time_t
- их много, и те, которые принимают значение struct tm
, полученное из значения time_t
. И арифметика c на них не сложна.
Я отмечаю, что в некоторых отношениях как struct timeval
, так и struct timespec
недостаточно указаны в POSIX. Что означает знак tv_usec
или tv_nsec
части struct timeval
или struct timespec
, если компонент tv_sec
отрицательный (см. Секунды с начала эпохи - Если год <1970 или значение отрицательное, отношение не определено </em>). POSIX оставляет поведение отрицательных значений tv_sec
неопределенным, что, вероятно, разумно, но делает жизнь немного труднее. Конечно, есть также вопросы: «Когда какая часть какой страны переключилась между юлианским и григорианским календарями?» и "был ли год ноль?" с этим также придется иметь дело. Когда time_t
было 32-битным числом, оно доходило до декабря 1901 года, что в значительной степени устраняет проблемы (но Россия не переключалась с юлианского на григорианский до Октябрьской революции, которая произошла в ноябре по григорианскому календарю). ). Теперь, когда time_t
обычно является 64-битным числом, годы B C (или BCE) также становятся представимыми.
Будьте внимательны при печати части tv_usec
или tv_nsec
. Не забудьте добавить достаточно начальных нулей, используя %.6d
для микросекунд, %.9ld
для наносекунд, где необходимый спецификатор преобразования (d
против ld
против ...) для tv_usec
не определен четко в POSIX - но d
обычно правильно. (Член tv_nsec
- это long
; это просто и надежно.)