Если у вас есть 64-разрядной системы, такие как Mac OS X (10,11 El Capitan используется), то это работает:
#include <inttypes.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
int y1 = 27440;
int m1 = 5;
int d1 = 1;
int y2 = 5660;
int m2 = 1;
int d2 = 24;
struct tm tm1 = { .tm_year = y1 - 1900, .tm_mon = m1 - 1, .tm_mday = d1 };
struct tm tm2 = { .tm_year = y2 - 1900, .tm_mon = m2 - 1, .tm_mday = d2 };
time_t t1 = mktime(&tm1);
time_t t2 = mktime(&tm2);
size_t dt = t1 - t2; // Dodgy assignment…I get away with it, but…
char buffer[128];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm1);
printf("t1 = %20s\n", buffer);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm2);
printf("t2 = %20s\n", buffer);
printf("t1 = %" PRIdMAX "\n", (intmax_t)t1);
printf("t2 = %" PRIdMAX "\n", (intmax_t)t2);
printf("dt = %zu seconds\n", dt);
printf("dt = %zu hours\n", dt/3600);
printf("dt = %zu days\n", dt/(24 * 3600));
return 0;
}
Выход я получаю:
t1 = 27440-05-01 00:00:00
t2 = 5660-01-24 00:00:00
t1 = 803766009600
t2 = 116447184000
dt = 687318825600 seconds
dt = 190921896 hours
dt = 7955079 days
Вещи не так уж хороши, пытаясь вернуться к ретроспективе. Разделив обе значения года на 10 выходов:
t1 = 2744-05-01 00:00:00
t2 = 0566-01-24 00:00:00
t1 = 24435504000
t2 = -1
dt = 24435504001 seconds
dt = 6787640 hours
dt = 282818 days
Обратите внимание, что -1
указывает на ошибку; система не желает играть с датами в первом тысячелетии (что делает вычисления dt
неточными). AFAICT, на Mac, mktime()
не идет еще дальше во времени, чем могут идти 32-битные знаковые значения - он принимает 1902-01-01, но отклоняет 1901-01-01.Предел 32-бит:
-2147483647 = Fri Dec 13 12:45:53 1901 (US/Pacific)
Код испытания:
static int test_year(int year)
{
struct tm tm1 = { .tm_year = year - 1900, .tm_mon = 0, .tm_mday = 1 };
time_t t1 = mktime(&tm1);
return (t1 != -1);
}
static void early_year(void)
{
int y_lo = 566;
int y_hi = 1902;
assert(test_year(y_lo) == 0);
assert(test_year(y_hi) == 1);
while (y_lo != y_hi)
{
int y_md = (y_lo + y_hi)/2;
printf("lo = %4d; hi = %4d; md = %4d\n", y_lo, y_hi, y_md);
if (test_year(y_md) == 0)
y_lo = y_md + 1;
else
y_hi = y_md - 1;
}
printf("Valid back to %4d\n", y_lo);
}
Результат вызова этого кода:
lo = 566; hi = 1902; md = 1234
lo = 1235; hi = 1902; md = 1568
lo = 1569; hi = 1902; md = 1735
lo = 1736; hi = 1902; md = 1819
lo = 1820; hi = 1902; md = 1861
lo = 1862; hi = 1902; md = 1882
lo = 1883; hi = 1902; md = 1892
lo = 1893; hi = 1902; md = 1897
lo = 1898; hi = 1902; md = 1900
lo = 1901; hi = 1902; md = 1901
Valid back to 1902
YMMV, как говорится; это будет зависеть от системы, над которой вы работаете. Обратите внимание, что чем дальше вы заходите вовремя, тем менее надежными являются часы и календари. Игнорируя такие тонкости, как 30 февраля 1712 года (в Швеции), вы получаете самые разные даты между 1584 и 20-м годами для дат, когда страны переключались с юлианского календаря на григорианский календарь (1752 год был датой перехода для Великобритании и ее колоний, например). Обычно люди применяют календарь «пролепит-григорианский» назад.
Это зависит от вашего O/S и библиотеки, и «bittiness» из вашей машины. 32-разрядные системы могут иметь проблемы за пределами диапазона 1902..2037 (32-разрядные целые числа, основанные на 1970-01-01 00:00:00 +00: 00 в качестве эпохи). 64-разрядные системы часто имеют 64-разрядный тип 'time_t', а диапазон дат на них является очень большим (смерть шкалы универсума). Да, функции знают о високосных годах. Понимают ли они все капризы того, когда изменилась область мира от юлианского до григорианского календаря (если она действительно соблюдалась) - это отдельное обсуждение. Часовые пояса тоже сложны! –
Возможный дубликат [Как распечатать временную разницу в точности миллисекунд и наносекунды?] (Http://stackoverflow.com/questions/16275444/how-to-print-time-difference-in-accuracy-of-milliseconds-and -nanoseconds) –
@OlexandrKravchuk: Почему это как дубликат? Это целые секунды, а не миллисекунды или наносекунды, не так ли? –