77 lines
1.6 KiB
Rust
77 lines
1.6 KiB
Rust
#[cfg(feature = "serde")]
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use {
|
|
crate::SECONDS_PER_DAY,
|
|
std::{cmp, fmt, num::ParseIntError, str::FromStr},
|
|
};
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
|
pub enum Year {
|
|
Normal(i32),
|
|
Leap(i32),
|
|
}
|
|
|
|
impl Year {
|
|
pub fn new(year: i32) -> Self {
|
|
if year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) {
|
|
Self::Leap(year)
|
|
} else {
|
|
Self::Normal(year)
|
|
}
|
|
}
|
|
|
|
pub fn days(&self) -> u16 {
|
|
match self {
|
|
Self::Normal(_) => 365,
|
|
Self::Leap(_) => 366,
|
|
}
|
|
}
|
|
|
|
pub fn seconds(&self) -> i64 {
|
|
self.days() as i64 * SECONDS_PER_DAY
|
|
}
|
|
|
|
pub fn get(&self) -> i32 {
|
|
match self {
|
|
Self::Normal(y) | Self::Leap(y) => *y,
|
|
}
|
|
}
|
|
|
|
pub fn next(&self) -> Self {
|
|
Self::new(self.get() + 1)
|
|
}
|
|
|
|
pub fn previous(&self) -> Self {
|
|
Self::new(self.get() - 1)
|
|
}
|
|
}
|
|
|
|
impl Ord for Year {
|
|
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
|
self.get().cmp(&other.get())
|
|
}
|
|
}
|
|
|
|
impl PartialOrd for Year {
|
|
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
|
Some(self.cmp(other))
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Year {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(f, "{:>4}", self.get())
|
|
}
|
|
}
|
|
|
|
impl FromStr for Year {
|
|
type Err = ParseIntError;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
let year: i32 = s.parse()?;
|
|
Ok(Self::new(year))
|
|
}
|
|
}
|