epoch-rs/src/year.rs

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))
}
}