cftime_rs/datetimes/
standard.rs1use crate::calendars::Calendar;
2use crate::datetimes::traits::{CalendarDatetime, IsLeap};
3use crate::timezone::Tz;
4use crate::utils::{
5 get_timestamp_from_hms, get_timestamp_from_ymd, get_ymd_hms_from_timestamp, is_leap_gregorian,
6 is_leap_julian,
7};
8
9use super::traits::CalendarDatetimeCreator;
10pub struct StandardDatetime {
11 pub timestamp: i64,
12 pub nanoseconds: u32,
13 pub tz: Tz,
14 pub calendar: Calendar,
15}
16
17impl StandardDatetime {
18 pub fn new(timestamp: i64, nanoseconds: u32, tz: Tz) -> Self {
19 Self {
20 timestamp,
21 nanoseconds,
22 tz,
23 calendar: Calendar::Standard,
24 }
25 }
26}
27impl IsLeap for StandardDatetime {
28 fn is_leap(year: i64) -> bool {
29 if year < 1582 {
30 is_leap_julian(year)
31 } else {
32 is_leap_gregorian(year)
33 }
34 }
35}
36
37impl CalendarDatetime for StandardDatetime {
38 fn timestamp(&self) -> i64 {
39 self.timestamp
40 }
41 fn nanoseconds(&self) -> u32 {
42 self.nanoseconds
43 }
44 fn calendar(&self) -> Calendar {
45 self.calendar
46 }
47 fn timezone(&self) -> Tz {
48 self.tz
49 }
50 fn ymd_hms(&self) -> Result<(i64, u8, u8, u8, u8, u8), crate::errors::Error> {
51 let gregorian_begin = get_timestamp_from_ymd::<StandardDatetime>(1582, 10, 15)?;
52 let mut timestamp = self.timestamp;
53 if self.timestamp < gregorian_begin {
54 let seconds_in_10_days = 10 * 24 * 60 * 60;
55 timestamp -= seconds_in_10_days
56 }
57 Ok(get_ymd_hms_from_timestamp::<StandardDatetime>(timestamp))
58 }
59}
60
61impl CalendarDatetimeCreator for StandardDatetime {
62 fn from_timestamp(timestamp: i64, _nanoseconds: u32) -> Self {
63 Self {
64 timestamp,
65 nanoseconds: 0,
66 tz: Tz::new(0, 0).unwrap(),
67 calendar: Calendar::Standard,
68 }
69 }
70 fn from_ymd_hms(
71 year: i64,
72 month: u8,
73 day: u8,
74 hour: u8,
75 minute: u8,
76 second: f32,
77 ) -> Result<Self, crate::errors::Error> {
78 let (mut timestamp, nanoseconds) = get_timestamp_from_hms(hour, minute, second)?;
79 if year == 1582
80 && month == 10
81 && ((day == 4 && (hour > 0 || minute > 0 || second > 0.0)) || (5..15).contains(&day))
82 {
83 return Err(crate::errors::Error::InvalidDate(
84 "Date between 1582-10-04 and 1582-10-15 are not defined in the standard calendar"
85 .to_string(),
86 ));
87 }
88 if year < 1582 || (year == 1582 && month < 10) || (year == 1582 && month == 10 && day < 15)
89 {
90 timestamp += 10 * 24 * 60 * 60
92 }
93
94 timestamp += get_timestamp_from_ymd::<StandardDatetime>(year, month, day)?;
95 Ok(Self {
96 timestamp,
97 nanoseconds,
98 tz: Tz::new(0, 0).unwrap(),
99 calendar: Calendar::Standard,
100 })
101 }
102}