tiger_lib/
date.rs

1//! The [`Date`] type represents in-game dates.
2
3use std::fmt::{Display, Error, Formatter};
4use std::str::FromStr;
5
6#[cfg(feature = "hoi4")]
7use crate::game::Game;
8use crate::token::Token;
9
10#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
11pub struct Date {
12    year: i16,
13    month: i8,
14    day: i8,
15    #[cfg(feature = "hoi4")]
16    hour: i8,
17}
18
19impl Date {
20    pub fn new(year: i16, month: i8, day: i8) -> Self {
21        Date {
22            year,
23            month,
24            day,
25            #[cfg(feature = "hoi4")]
26            hour: 1,
27        }
28    }
29}
30
31impl FromStr for Date {
32    type Err = Error;
33
34    fn from_str(s: &str) -> Result<Self, Self::Err> {
35        // Trailing whitespace is accepted by the engine
36        let s = s.trim_end();
37
38        let mut splits = s.split('.');
39        let year = splits.next().ok_or(Error)?;
40        let month = splits.next().unwrap_or("1");
41        let mut day = splits.next().unwrap_or("1");
42        #[cfg(feature = "hoi4")]
43        let mut hour = splits.next().unwrap_or("1");
44        // Error if there is another field, but do allow a trailing dot
45        if let Some(next) = splits.next() {
46            if !next.is_empty() {
47                return Err(Error);
48            }
49        }
50        if day.is_empty() {
51            day = "1";
52        }
53        #[cfg(feature = "hoi4")]
54        if hour.is_empty() {
55            hour = "1";
56        }
57        Ok(Date {
58            year: year.parse().map_err(|_| Error)?,
59            month: month.parse().map_err(|_| Error)?,
60            day: day.parse().map_err(|_| Error)?,
61            #[cfg(feature = "hoi4")]
62            hour: hour.parse().map_err(|_| Error)?,
63        })
64    }
65}
66
67impl TryFrom<&Token> for Date {
68    type Error = Error;
69
70    fn try_from(value: &Token) -> Result<Self, Self::Error> {
71        value.as_str().parse()
72    }
73}
74
75impl Display for Date {
76    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
77        #[cfg(feature = "hoi4")]
78        if Game::is_hoi4() {
79            return write!(f, "{}.{}.{}.{}", self.year, self.month, self.day, self.hour);
80        }
81        write!(f, "{}.{}.{}", self.year, self.month, self.day)
82    }
83}