The Pedigree Project 0.1
RtcTimeAccounting.h
1/*
2 * Copyright (c) 2026, Pedigree Developers
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted.
6 */
7
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"
11
12#include <config.h>
13
14namespace RtcTimeAccounting {
15constexpr uint64_t NanosecondsPerSecond = 1000000000ULL;
16
17struct CivilTime {
18 size_t year;
19 uint8_t month;
20 uint8_t day;
21 uint8_t hour;
22 uint8_t minute;
23 uint8_t second;
24 uint64_t nanosecond;
25};
26
27inline bool isLeapYear(size_t year) {
28 return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
29}
30
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) {
34 return 31;
35 }
36 return month == 2 && isLeapYear(year) ? 29 : Days[month - 1];
37}
38
40inline uint64_t consumeElapsed(uint64_t observed, uint64_t& cursor) {
41 if (observed <= cursor) {
42 return 0;
43 }
44
45 const uint64_t delta = observed - cursor;
46 cursor = observed;
47 return delta;
48}
49
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)) {
55 ++elapsedSeconds;
56 time.nanosecond = remainder - (NanosecondsPerSecond - time.nanosecond);
57 } else {
58 time.nanosecond += remainder;
59 }
60
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;
68
69 while (days) {
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);
74 break;
75 }
76
77 days -= remainingInMonth + 1;
78 time.day = 1;
79 if (++time.month > 12) {
80 time.month = 1;
81 ++time.year;
82 }
83 }
84
85 return elapsedSeconds;
86}
87} // namespace RtcTimeAccounting
88
89#endif