8#ifndef PEDIGREE_KERNEL_MACHINE_MACH_PC_RTCTIMEACCOUNTING_H
9#define PEDIGREE_KERNEL_MACHINE_MACH_PC_RTCTIMEACCOUNTING_H
10#include "pedigree/kernel/processor/types.h"
14namespace RtcTimeAccounting {
15constexpr uint64_t NanosecondsPerSecond = 1000000000ULL;
27inline bool isLeapYear(
size_t year) {
28 return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
31inline uint8_t daysInMonth(
size_t year, uint8_t month) {
32 static constexpr uint8_t Days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
33 if (month < 1 || month > 12) {
36 return month == 2 && isLeapYear(year) ? 29 : Days[month - 1];
40inline uint64_t consumeElapsed(uint64_t observed, uint64_t& cursor) {
41 if (observed <= cursor) {
45 const uint64_t delta = observed - cursor;
51inline uint64_t advanceCivilTime(CivilTime& time, uint64_t delta) {
52 uint64_t elapsedSeconds = delta / NanosecondsPerSecond;
53 const uint64_t remainder = delta % NanosecondsPerSecond;
54 if (remainder >= (NanosecondsPerSecond - time.nanosecond)) {
56 time.nanosecond = remainder - (NanosecondsPerSecond - time.nanosecond);
58 time.nanosecond += remainder;
61 uint64_t total =
static_cast<uint64_t
>(time.second) + elapsedSeconds;
62 time.second =
static_cast<uint8_t
>(total % 60);
63 total =
static_cast<uint64_t
>(time.minute) + (total / 60);
64 time.minute =
static_cast<uint8_t
>(total % 60);
65 total =
static_cast<uint64_t
>(time.hour) + (total / 60);
66 time.hour =
static_cast<uint8_t
>(total % 24);
67 uint64_t days = total / 24;
70 const uint8_t monthDays = daysInMonth(time.year, time.month);
71 const uint64_t remainingInMonth = monthDays - time.day;
72 if (days <= remainingInMonth) {
73 time.day =
static_cast<uint8_t
>(time.day + days);
77 days -= remainingInMonth + 1;
79 if (++time.month > 12) {
85 return elapsedSeconds;