Repository URL to install this package:
|
Version:
3.10.1 ▾
|
// Copyright (c) 2019, Peter Ohler, All rights reserved.
#include "util.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#define SECS_PER_DAY 86400LL
#define SECS_PER_YEAR 31536000LL
#define SECS_PER_LEAP 31622400LL
#define SECS_PER_QUAD_YEAR (SECS_PER_YEAR * 3 + SECS_PER_LEAP)
#define SECS_PER_CENT (SECS_PER_QUAD_YEAR * 24 + SECS_PER_YEAR * 4)
#define SECS_PER_LEAP_CENT (SECS_PER_CENT + SECS_PER_DAY)
#define SECS_PER_QUAD_CENT (SECS_PER_CENT * 4 + SECS_PER_DAY)
static int64_t eom_secs[] = {
2678400, // January (31)
5097600, // February (28) 2419200 2505600
7776000, // March (31)
10368000, // April (30 2592000
13046400, // May (31)
15638400, // June (30)
18316800, // July (31)
20995200, // August (31)
23587200, // September (30)
26265600, // October (31)
28857600, // November (30)
31536000, // December (31)
};
static int64_t eom_leap_secs[] = {
2678400, // January (31)
5184000, // February (28) 2419200 2505600
7862400, // March (31)
10454400, // April (30 2592000
13132800, // May (31)
15724800, // June (30)
18403200, // July (31)
21081600, // August (31)
23673600, // September (30)
26352000, // October (31)
28944000, // November (30)
31622400, // December (31)
};
void
sec_as_time(int64_t secs, TimeInfo ti) {
int64_t qc = 0;
int64_t c = 0;
int64_t qy = 0;
int64_t y = 0;
bool leap = false;
int64_t *ms;
int m;
int shift = 0;
secs += 62167219200LL; // normalize to first day of the year 0
if (secs < 0) {
shift = -secs / SECS_PER_QUAD_CENT;
shift++;
secs += shift * SECS_PER_QUAD_CENT;
}
qc = secs / SECS_PER_QUAD_CENT;
secs = secs - qc * SECS_PER_QUAD_CENT;
if (secs < SECS_PER_LEAP) {
leap = true;
} else if (secs < SECS_PER_QUAD_YEAR) {
if (SECS_PER_LEAP <= secs) {
secs -= SECS_PER_LEAP;
y = secs / SECS_PER_YEAR;
secs = secs - y * SECS_PER_YEAR;
y++;
leap = false;
}
} else if (secs < SECS_PER_LEAP_CENT) { // first century in 400 years is a leap century (one extra day)
qy = secs / SECS_PER_QUAD_YEAR;
secs = secs - qy * SECS_PER_QUAD_YEAR;
if (secs < SECS_PER_LEAP) {
leap = true;
} else {
secs -= SECS_PER_LEAP;
y = secs / SECS_PER_YEAR;
secs = secs - y * SECS_PER_YEAR;
y++;
}
} else {
secs -= SECS_PER_LEAP_CENT;
c = secs / SECS_PER_CENT;
secs = secs - c * SECS_PER_CENT;
c++;
if (secs < SECS_PER_YEAR * 4) {
y = secs / SECS_PER_YEAR;
secs = secs - y * SECS_PER_YEAR;
} else {
secs -= SECS_PER_YEAR * 4;
qy = secs / SECS_PER_QUAD_YEAR;
secs = secs - qy * SECS_PER_QUAD_YEAR;
qy++;
if (secs < SECS_PER_LEAP) {
leap = true;
} else {
secs -= SECS_PER_LEAP;
y = secs / SECS_PER_YEAR;
secs = secs - y * SECS_PER_YEAR;
y++;
}
}
}
ti->year = (int)((qc - (int64_t)shift) * 400 + c * 100 + qy * 4 + y);
if (leap) {
ms = eom_leap_secs;
} else {
ms = eom_secs;
}
for (m = 1; m <= 12; m++, ms++) {
if (secs < *ms) {
if (1 < m) {
secs -= *(ms - 1);
}
ti->mon = m;
break;
}
}
ti->day = (int)(secs / 86400LL);
secs = secs - (int64_t)ti->day * 86400LL;
ti->day++;
ti->hour = (int)(secs / 3600LL);
secs = secs - (int64_t)ti->hour * 3600LL;
ti->min = (int)(secs / 60LL);
secs = secs - (int64_t)ti->min * 60LL;
ti->sec = (int)secs;
}