#pragma once
namespace panda { namespace time {
char* readfile (const char*);
inline int64_t char8_to_int64 (const char* source) {
return *((int64_t*) source);
}
inline int is_leap_year (int32_t year) {
return (year % 4) == 0 && ((year % 25) != 0 || (year % 16) == 0);
}
// DAYS PASSED SINCE 1 Jan 0001 00:00:00 TILL 1 Jan <year> 00:00:00
inline ptime_t christ_days (int32_t year) {
ptime_t yearpos = (ptime_t)year + 2147483999U;
ptime_t ret = yearpos*365;
yearpos >>= 2;
ret += yearpos;
yearpos /= 25;
ret -= yearpos - (yearpos >> 2) + (ptime_t)146097*5368710;
return ret;
}
// GIVEN DAYS PASSED SINCE 1 Jan 0001 00:00:00 CALCULATES REAL YEAR AND DAYS REMAINDER - YDAY [0-365]
inline void christ_year (ptime_t days, int32_t &year, int32_t &remainder) {
// 1-st step: separate FULL QUAD CENTURIES
ptime_t tmp = (days + OUTLIM_DAY_BY_QCENT) % DAYS_PER_QCENT;
year = (days - tmp)/DAYS_PER_QCENT * 400;
days = tmp;
// 2-nd step: separate FULL CENTURIES, condition fixes QCENT -> CENT border
if (unlikely(days == DAYS_PER_CENT*4)) {
year += 300;
days = DAYS_PER_CENT;
} else {
year += days/DAYS_PER_CENT * 100;
days %= DAYS_PER_CENT;
}
// 3-rd step: separate FULL QUAD YEARS, no border fix needed
year += days/DAYS_PER_QYEAR * 4;
days %= DAYS_PER_QYEAR;
// 4-th step: separate FULL YEARS, condition fixes QYEAR -> YEAR border
if (unlikely(days == DAYS_PER_YEAR*4)) {
year += 4; // actually 3, but we must add 1 to result year, as the start is 1-st year, not 0-th
remainder = 365;
} else {
year += days/DAYS_PER_YEAR + 1; // we must add 1 to result year, as the start is 1-st year, not 0-th
remainder = days % DAYS_PER_YEAR;
}
}
inline void dt2tm (struct tm &to, dt &from) {
to.tm_sec = from.sec;
to.tm_min = from.min;
to.tm_hour = from.hour;
to.tm_mday = from.mday;
to.tm_mon = from.mon;
to.tm_year = from.year-1900;
to.tm_isdst = from.isdst;
to.tm_wday = from.wday;
to.tm_yday = from.yday;
#ifndef PTIME_OSTYPE_WIN
to.tm_gmtoff = from.gmtoff;
to.tm_zone = from.zone;
#endif
}
inline void tm2dt (dt &to, struct tm &from) {
to.sec = from.tm_sec;
to.min = from.tm_min;
to.hour = from.tm_hour;
to.mday = from.tm_mday;
to.mon = from.tm_mon;
to.year = from.tm_year+1900;
to.isdst = from.tm_isdst;
to.wday = from.tm_wday;
to.yday = from.tm_yday;
#ifdef PTIME_OSTYPE_WIN
to.gmtoff = 0;
to.n_zone = 0;
#else
to.gmtoff = from.tm_gmtoff;
to.n_zone = char8_to_int64(from.tm_zone);
#endif
}
inline int days_in_month (int32_t year, uint8_t month) {
return DAYS_IN_MONTH[is_leap_year(year)][month];
}
};};