cftime_rs/datetimes/
day_360.rs1use 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 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 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}