1 use std::{convert, fmt, io}; 2 3 use crate::{ 4 error::FendError, 5 result::FResult, 6 serialize::{Deserialize, Serialize}, 7 }; 8 9 #[derive(Copy, Clone, Eq, PartialEq)] 10 pub(crate) struct Year(i32); 11 12 impl Year { new(year: i32) -> Self13 pub(crate) fn new(year: i32) -> Self { 14 assert!(year != 0, "year 0 is invalid"); 15 Self(year) 16 } 17 18 #[inline] value(self) -> i3219 pub(crate) fn value(self) -> i32 { 20 self.0 21 } 22 next(self) -> Self23 pub(crate) fn next(self) -> Self { 24 if self.value() == -1 { 25 Self::new(1) 26 } else { 27 Self::new(self.value() + 1) 28 } 29 } 30 prev(self) -> Self31 pub(crate) fn prev(self) -> Self { 32 if self.value() == 1 { 33 Self::new(-1) 34 } else { 35 Self::new(self.value() - 1) 36 } 37 } 38 is_leap_year(self) -> bool39 pub(crate) fn is_leap_year(self) -> bool { 40 if self.value() % 400 == 0 { 41 true 42 } else if self.value() % 100 == 0 { 43 false 44 } else { 45 self.value() % 4 == 0 46 } 47 } 48 number_of_days(self) -> u1649 pub(crate) fn number_of_days(self) -> u16 { 50 if self.is_leap_year() { 51 366 52 } else { 53 365 54 } 55 } 56 serialize(self, write: &mut impl io::Write) -> FResult<()>57 pub(crate) fn serialize(self, write: &mut impl io::Write) -> FResult<()> { 58 self.value().serialize(write)?; 59 Ok(()) 60 } 61 deserialize(read: &mut impl io::Read) -> FResult<Self>62 pub(crate) fn deserialize(read: &mut impl io::Read) -> FResult<Self> { 63 Self::try_from(i32::deserialize(read)?).map_err(|_| FendError::DeserializationError) 64 } 65 } 66 67 pub(crate) struct InvalidYearError; 68 69 impl convert::TryFrom<i32> for Year { 70 type Error = InvalidYearError; 71 try_from(year: i32) -> Result<Self, Self::Error>72 fn try_from(year: i32) -> Result<Self, Self::Error> { 73 if year == 0 { 74 Err(InvalidYearError) 75 } else { 76 Ok(Self(year)) 77 } 78 } 79 } 80 81 impl fmt::Debug for Year { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 83 if self.value() < 0 { 84 write!(f, "{} BC", -self.0) 85 } else { 86 write!(f, "{}", self.0) 87 } 88 } 89 } 90 91 impl fmt::Display for Year { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 93 if self.value() < 0 { 94 write!(f, "{} BC", -self.0) 95 } else { 96 write!(f, "{}", self.0) 97 } 98 } 99 } 100 101 #[cfg(test)] 102 mod tests { 103 use super::*; 104 105 #[test] 106 #[should_panic(expected = "year 0 is invalid")] year_0()107 fn year_0() { 108 Year::new(0); 109 } 110 111 #[test] negative_year_string()112 fn negative_year_string() { 113 assert_eq!(Year::new(-823).to_string(), "823 BC"); 114 } 115 } 116