/* _,.---._ .-._ .--.-. ,--.--------. * _,..---._ ,-.' , - `. /==/ \ .-._/==/ //==/, - , -\ * /==/, - \ /==/_, , - \|==|, \/ /, |==\ -\\==\.-. - ,-./ * |==| _ _\==| .=. |==|- \| | \==\- \`--`\==\- \ * |==| .=. |==|_ : ;=: - |==| , | -| `--`-' \==\_ \ * |==|,| | -|==| , '=' |==| - _ | |==|- | * |==| '=' /\==\ - ,_ /|==| /\ , | |==|, | * |==|-, _`/ '.='. - .' /==/, | |- | /==/ -/ * `-.`.____.' `--`--'' `--`./ `--` `--`--` * _ __ ,---. .-._ .=-.-. _,.----. * .-`.' ,`..--.' \ /==/ \ .-._ /==/_ /.' .' - \ * /==/, - \==\-/\ \ |==|, \/ /, /==|, |/==/ , ,-' * |==| _ .=. /==/-|_\ | |==|- \| ||==| ||==|- | . * |==| , '=',\==\, - \ |==| , | -||==|- ||==|_ `-' \ * |==|- '..'/==/ - ,| |==| - _ ||==| ,||==| _ , | * |==|, | /==/- /\ - \|==| /\ , ||==|- |\==\. / * /==/ - | \==\ _.\=\.-'/==/, | |- |/==/. / `-.`.___.-' * `--`---' `--` `--`./ `--``--`-` * * @(#)Copyright (c) 2024, Nathan D. Fisher. * * This is free software. It comes with NO WARRANTY. * Permission to use, modify and distribute this source code * is granted subject to the following conditions. * 1/ that the above copyright notice and this notice * are preserved in all copies and that due credit be given * to the author. * 2/ that any changes to this code are clearly commented * as such so that the author does not get blamed for bugs * other than his own. */ #include "epoch.h" #include #include #include int32_t dateTimeGetYear(DateTime *self) { return self->year.year; } int64_t dateTimeGetTimestampNaive(DateTime *self) { int64_t seconds = 0; Year year = (Year){ .tag = normalYear, .year = 1970 }; Month month = January; int32_t oldyear = yearGetInner(&self->year); if (oldyear < 1970) { while (yearGetInner(&year) > oldyear) { yearDecrement(&year); seconds -= yearGetSeconds(&year); } } else if (oldyear > 1970) { while (yearGetInner(&year) < oldyear) { seconds += yearGetSeconds(&year); yearIncrement(&year); } } while (month < self->month) { seconds += monthGetSeconds(month, &self->year); monthIncrement(&month); } seconds += ((int64_t)self->day - 1) * SECONDS_PER_DAY; seconds += (int64_t)self->hour * SECONDS_PER_HOUR; seconds += (int64_t)self->minute * 60; seconds += (int64_t)self->second; return seconds; } int64_t dateTimeGetTimestamp(DateTime *self) { int64_t seconds = dateTimeGetTimestampNaive(self); seconds += timezoneAsSeconds(&self->zone); return seconds; } void dateTimeGetTimespec(DateTime *self, struct timespec * ts) { ts->tv_nsec = self->nanoseconds; ts->tv_sec = (time_t)dateTimeGetTimestamp(self); } Weekday dateTimeGetWeekday(DateTime *self) { int64_t ts = dateTimeGetTimestampNaive(self); ts /= SECONDS_PER_DAY; return ts % 7; } void dateTimeFromTimestampParts(int64_t seconds, int64_t nanoseconds, DateTime *dt) { int ret = 0; dt->nanoseconds = nanoseconds; dt->zone.tag = UTC; if (seconds < 0) { yearNew(&dt->year, 1969); while (seconds < yearGetSeconds(&dt->year)) { seconds += yearGetSeconds(&dt->year); yearDecrement(&dt->year); } dt->month = December; while (ret == 0) { if (-seconds < monthGetSeconds(dt->month, &dt->year)) break; seconds += monthGetSeconds(dt->month, &dt->year); ret = monthDecrement(&dt->month); } ret = 0; dt->day = monthGetDays(dt->month, &dt->year); while (dt->day > 0 && seconds < -SECONDS_PER_DAY) { seconds += SECONDS_PER_DAY; dt->day -=1; } dt->hour = 23; while (dt->hour > 0 && seconds < -SECONDS_PER_HOUR) { seconds += SECONDS_PER_HOUR; dt->hour -= 1; } dt->minute = 59; while (dt->minute > 0 && seconds < -60) { seconds += 60; dt->minute -= 1; } dt->second = seconds + 60; } else if (seconds > 0) { yearNew(&dt->year, 1970); while (yearGetSeconds(&dt->year) < seconds) { seconds -= yearGetSeconds(&dt->year); yearIncrement(&dt->year); } dt->month = January; while (ret == 0 && monthGetSeconds(dt->month, &dt->year) < seconds) { seconds -= (int64_t)monthGetSeconds(dt->month, &dt->year); ret = monthIncrement(&dt->month); } dt->day = seconds / SECONDS_PER_DAY + 1; seconds %= SECONDS_PER_DAY; dt->hour = seconds / SECONDS_PER_HOUR; seconds %= SECONDS_PER_HOUR; dt->minute = seconds / 60; seconds %= 60; dt->second = seconds; } else { yearNew(&dt->year, 1970); dt->month = January; dt->day = 1; dt->hour = 0; dt->minute = 0; dt->second = 0; } } void dateTimeFromTimespec(struct timespec *ts, DateTime *dt) { dateTimeFromTimestampParts(ts->tv_sec, ts->tv_nsec, dt); }