cftime_rs/datetimes/
day_360.rs

1use crate::calendars::Calendar;
2use crate::constants;
3use crate::datetimes::traits::CalendarDatetime;
4use crate::timezone::Tz;
5use crate::utils::{get_hms_from_timestamp, get_timestamp_from_hms};
6
7use super::traits::CalendarDatetimeCreator;
8pub struct Day360Datetime {
9    pub timestamp: i64,
10    pub nanoseconds: u32,
11    pub tz: Tz,
12    pub calendar: Calendar,
13}
14
15impl Day360Datetime {
16    pub fn new(timestamp: i64, nanoseconds: u32, tz: Tz) -> Self {
17        Self {
18            timestamp,
19            nanoseconds,
20            tz,
21            calendar: Calendar::Day360,
22        }
23    }
24}
25
26impl CalendarDatetime for Day360Datetime {
27    fn timestamp(&self) -> i64 {
28        self.timestamp
29    }
30    fn nanoseconds(&self) -> u32 {
31        self.nanoseconds
32    }
33    fn timezone(&self) -> Tz {
34        self.tz
35    }
36    fn calendar(&self) -> Calendar {
37        self.calendar
38    }
39
40    fn ymd_hms(&self) -> Result<(i64, u8, u8, u8, u8, u8), crate::errors::Error> {
41        let mut nb_days = self.timestamp / constants::SECS_PER_DAY as i64;
42        let remaining_seconds = self.timestamp % constants::SECS_PER_DAY as i64;
43        if remaining_seconds < 0 {
44            nb_days -= 1
45        }
46        let (nb_year, remaining_days) = (nb_days.div_euclid(360), nb_days.rem_euclid(360));
47
48        let (mut month, day) = (remaining_days / 30, remaining_days % 30);
49        month = (month + 12) % 12;
50        let year = constants::UNIX_DEFAULT_YEAR + nb_year;
51        let (hour, minute, second) = get_hms_from_timestamp(remaining_seconds);
52        Ok((
53            year,
54            (month + 1) as u8,
55            (day + 1) as u8,
56            hour,
57            minute,
58            second,
59        ))
60    }
61}
62
63impl CalendarDatetimeCreator for Day360Datetime {
64    fn from_timestamp(timestamp: i64, nanoseconds: u32) -> Self {
65        Self {
66            timestamp,
67            nanoseconds,
68            tz: Tz::new(0, 0).unwrap(),
69            calendar: Calendar::Day360,
70        }
71    }
72    fn from_ymd_hms(
73        year: i64,
74        month: u8,
75        day: u8,
76        hour: u8,
77        minute: u8,
78        second: f32,
79    ) -> Result<Self, crate::errors::Error> {
80        let (mut timestamp, nanoseconds) = get_timestamp_from_hms(hour, minute, second)?;
81
82        // Calculate years and months
83        let mut year = year;
84        let month = month as i64 - 1;
85        let day = day as i64 - 1;
86
87        loop {
88            if year == constants::UNIX_DEFAULT_YEAR {
89                break;
90            }
91
92            if year > constants::UNIX_DEFAULT_YEAR {
93                timestamp += 360 * constants::SECS_PER_DAY as i64;
94                year -= 1;
95            } else {
96                timestamp -= 360 * constants::SECS_PER_DAY as i64;
97                year += 1;
98            }
99        }
100
101        // Calculate days
102        timestamp += (month * 30 + day) * constants::SECS_PER_DAY as i64;
103
104        Ok(Self {
105            calendar: Calendar::Day360,
106            timestamp,
107            tz: Tz::new(0, 0).unwrap(),
108            nanoseconds,
109        })
110    }
111}