pub struct Calendar {
hours: u8,
minutes: u8,
seconds: u8,
day: u8,
month: u8,
year: u16,
}
impl Calendar {
pub fn new(hours: u8, minutes: u8, seconds: u8, day: u8, month: u8, year: u16) -> Self {
Self {
hours,
minutes,
seconds,
day,
month,
year,
}
}
pub fn from_seconds(base: Calendar, seconds: u32) -> Self {
let total_seconds = seconds + base.seconds as u32;
let seconds = total_seconds % 60;
let total_minutes = total_seconds / 60 + base.minutes as u32;
let minutes = total_minutes % 60;
let total_hours = total_minutes / 60 + base.hours as u32;
let hours = total_hours % 24;
let total_days = total_hours / 24 + base.day as u32;
let day = total_days % 30; // TODO...
// the current month and year has to be known prior to the calculation of the day
Self {
seconds: seconds as u8,
minutes: minutes as u8,
hours: hours as u8,
day: day as u8,
month: base.month,
year: base.year,
}
}
pub fn hours(&self) -> u8 {
self.hours
}
pub fn minutes(&self) -> u8 {
self.minutes
}
pub fn seconds(&self) -> u8 {
self.seconds
}
pub fn day(&self) -> u8 {
self.day
}
pub fn month(&self) -> u8 {
self.month
}
pub fn year(&self) -> u16 {
self.year
}
pub fn second_elapsed(&mut self) {
self.seconds = (self.seconds + 1) % 60;
let minute_elapsed = self.seconds == 0;
self.minutes = (self.minutes + if minute_elapsed { 1 } else { 0 }) % 60;
let hour_elapsed = minute_elapsed && self.minutes == 0;
self.hours = (self.hours + if hour_elapsed { 1 } else { 0 }) % 24;
let day_elapsed = hour_elapsed && self.hours == 0;
let day = self.day - 1 + if day_elapsed { 1 } else { 0 };
let days_in_month = Self::days_in_month(self.month, Self::is_leap_year(self.year));
self.day = day % days_in_month + 1;
let month_elapsed = day_elapsed && self.day == 1;
self.month = (self.month - 1 + if month_elapsed { 1 } else { 0 }) % 12 + 1;
let year_elapsed = month_elapsed && self.month == 1;
self.year += if year_elapsed { 1 } else { 0 };
}
fn is_leap_year(year: u16) -> bool {
matches!(year % 4, 0 if year % 100 != 0 || year % 400 == 0)
}
fn days_in_month(month: u8, leap_year: bool) -> u8 {
match month {
2 if leap_year => 29,
2 => 28,
1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
4 | 6 | 9 | 11 => 31,
_ => panic!(),
}
}
}