1use crate::utils::get_datetime_and_unit_from_units;
4use crate::{calendars::Calendar, datetime::CFDatetime};
5
6pub trait CFDecoder {
8 fn decode_cf(
19 &self,
20 units: &str,
21 calendar: Calendar,
22 ) -> Result<CFDatetime, crate::errors::Error>;
23}
24
25macro_rules! impl_cf_decoder {
26 ($type:ty) => {
27 impl CFDecoder for $type {
28 fn decode_cf(
29 &self,
30 units: &str,
31 calendar: Calendar,
32 ) -> Result<CFDatetime, crate::errors::Error> {
33 let (cf_datetime, unit) = get_datetime_and_unit_from_units(units, calendar)?;
34 let duration = unit.to_duration(calendar);
35 let result = (&cf_datetime + (&duration * *self))?;
36
37 Ok(result)
38 }
39 }
40 };
41}
42
43impl_cf_decoder!(i64);
44impl_cf_decoder!(i32);
45impl_cf_decoder!(f32);
46impl_cf_decoder!(f64);
47
48pub trait VecCFDecoder {
49 fn decode_cf(
50 &self,
51 units: &str,
52 calendar: Calendar,
53 ) -> Result<Vec<CFDatetime>, crate::errors::Error>;
54}
55
56macro_rules! impl_vec_cf_decoder {
57 ($type:ty) => {
58 impl VecCFDecoder for Vec<$type> {
59 fn decode_cf(
60 &self,
61 units: &str,
62 calendar: Calendar,
63 ) -> Result<Vec<CFDatetime>, crate::errors::Error> {
64 let (cf_datetime, unit) = get_datetime_and_unit_from_units(units, calendar)?;
65 let duration = unit.to_duration(calendar);
66 let mut datetimes = Vec::with_capacity(self.len());
67 for value in self {
68 let new_datetime = &cf_datetime + (&duration * *value);
69 datetimes.push(new_datetime?);
70 }
71
72 Ok(datetimes)
73 }
74 }
75 };
76}
77
78impl_vec_cf_decoder!(i64);
79impl_vec_cf_decoder!(i32);
80impl_vec_cf_decoder!(f32);
81impl_vec_cf_decoder!(f64);
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn test_decode_i64_cf_with_hms() {
89 let to_decode = 2;
90 let units = "days since 2000-01-01 00:00:00";
91 let calendar = Calendar::Standard;
92
93 let result = to_decode.decode_cf(units, calendar);
94
95 assert!(result.is_ok());
97 let cf_datetime = result.unwrap();
98 let (year, month, day, hour, minute, second) = cf_datetime.ymd_hms().unwrap();
99 assert_eq!(
100 (year, month, day, hour, minute, second),
101 (2000, 1, 3, 0, 0, 0)
102 );
103 }
104 #[test]
105 fn test_decode_f64_cf_with_hms() {
106 let to_decode: f64 = 2.0;
107 let units = "hours since 2000-01-01 00:00:00";
108 let calendar = Calendar::Standard;
109
110 let result = to_decode.decode_cf(units, calendar);
111
112 assert!(result.is_ok());
114 let cf_datetime = result.unwrap();
115 let (year, month, day, hour, minute, second) = cf_datetime.ymd_hms().unwrap();
116 assert_eq!(
117 (year, month, day, hour, minute, second),
118 (2000, 1, 1, 2, 0, 0)
119 );
120 }
121
122 #[test]
123 fn test_decode_i32_vec_cf_with_hms() {
124 let to_decode = vec![0, 1, 2];
125 let units = "days since 2000-01-01 00:00:00";
126 let calendar = Calendar::Standard;
127
128 let datetimes_result = to_decode.decode_cf(units, calendar);
129
130 assert!(datetimes_result.is_ok());
132 let datetimes = datetimes_result.unwrap();
133 for (i, datetime) in datetimes.iter().enumerate() {
134 let (year, month, day, hour, minute, second) = datetime.ymd_hms().unwrap();
135 assert_eq!(
136 (year, month, day, hour, minute, second),
137 (2000, 1, (i + 1) as u8, 0, 0, 0)
138 );
139 }
140 }
141 #[test]
142 fn test_decode_f64_vec_cf_with_hms() {
143 let to_decode: Vec<f64> = vec![1.0, 1.25, 1.50, 1.75, 2.0];
144 let units = "hours since 2000-01-01 00:00:00";
145 let calendar = Calendar::Standard;
146
147 let datetimes_result = to_decode.decode_cf(units, calendar);
148
149 assert!(datetimes_result.is_ok());
151 let datetimes = datetimes_result.unwrap();
152 let (year, month, day, hour, minute, second) = datetimes[0].ymd_hms().unwrap();
153 assert_eq!(
154 (year, month, day, hour, minute, second),
155 (2000, 1, 1, 1, 0, 0)
156 );
157 let (year, month, day, hour, minute, second) = datetimes[1].ymd_hms().unwrap();
158 assert_eq!(
159 (year, month, day, hour, minute, second),
160 (2000, 1, 1, 1, 15, 0)
161 );
162 let (year, month, day, hour, minute, second) = datetimes[2].ymd_hms().unwrap();
163 assert_eq!(
164 (year, month, day, hour, minute, second),
165 (2000, 1, 1, 1, 30, 0)
166 );
167 let (year, month, day, hour, minute, second) = datetimes[3].ymd_hms().unwrap();
168 assert_eq!(
169 (year, month, day, hour, minute, second),
170 (2000, 1, 1, 1, 45, 0)
171 );
172 let (year, month, day, hour, minute, second) = datetimes[4].ymd_hms().unwrap();
173 assert_eq!(
174 (year, month, day, hour, minute, second),
175 (2000, 1, 1, 2, 0, 0)
176 );
177 }
178 #[test]
179 fn test_decode_95795_from_days() {
180 let to_decode: Vec<f32> = vec![95795.0];
184 let units = "days since 1970-01-01";
185 let calendar = Calendar::Standard;
186
187 let datetimes_result = to_decode.decode_cf(units, calendar);
188 let datetimes = datetimes_result.unwrap();
189 let (year, month, day, hour, minute, second) = datetimes[0].ymd_hms().unwrap();
190 assert_eq!(
191 (year, month, day, hour, minute, second),
192 (2232, 4, 12, 0, 0, 0)
193 );
194
195 let to_decode: Vec<f64> = vec![95795.0];
196 let units = "days since 1970-01-01";
197 let calendar = Calendar::Standard;
198
199 let datetimes_result = to_decode.decode_cf(units, calendar);
200 let datetimes = datetimes_result.unwrap();
201 let (year, month, day, hour, minute, second) = datetimes[0].ymd_hms().unwrap();
202 assert_eq!(
203 (year, month, day, hour, minute, second),
204 (2232, 4, 12, 0, 0, 0)
205 );
206 let to_decode: Vec<i64> = vec![95795];
207 let units = "days since 1970-01-01";
208 let calendar = Calendar::Standard;
209
210 let datetimes_result = to_decode.decode_cf(units, calendar);
211 let datetimes = datetimes_result.unwrap();
212 let (year, month, day, hour, minute, second) = datetimes[0].ymd_hms().unwrap();
213 assert_eq!(
214 (year, month, day, hour, minute, second),
215 (2232, 4, 12, 0, 0, 0)
216 );
217 }
218 #[test]
219 fn test_vec_decode_cf_days() {
220 let units = "days since 0000-01-01 00:00:00";
222 let numbers = vec![730487.0, 730488.0416666666, 730489.0833333334];
224 let result = numbers.decode_cf(units, Calendar::Standard).unwrap();
225 let datetimes = vec![
226 CFDatetime::from_ymd_hms(2000, 1, 1, 0, 0, 0.0, Calendar::Standard).unwrap(),
227 CFDatetime::from_ymd_hms(2000, 1, 2, 1, 0, 0.0, Calendar::Standard).unwrap(),
228 CFDatetime::from_ymd_hms(2000, 1, 3, 2, 0, 0.0, Calendar::Standard).unwrap(),
229 ];
230 for (i, datetime) in datetimes.iter().enumerate() {
231 let expected_ymd_hms = datetime.ymd_hms().unwrap();
232 let result_ymd_hms = result[i].ymd_hms().unwrap();
233 println!("{}", result[i]);
234 assert_eq!(expected_ymd_hms, result_ymd_hms);
235 }
236
237 let units = "days since 0000-01-01 00:00:00";
248 let numbers: Vec<f32> = vec![730487.0, 730488.0416666666, 730489.0833333334];
249 let result = numbers.decode_cf(units, Calendar::Standard).unwrap();
250 let datetimes = vec![
251 CFDatetime::from_ymd_hms(2000, 1, 1, 0, 0, 0.0, Calendar::Standard).unwrap(),
252 CFDatetime::from_ymd_hms(2000, 1, 2, 1, 30, 0.0, Calendar::Standard).unwrap(),
253 CFDatetime::from_ymd_hms(2000, 1, 3, 1, 30, 0.0, Calendar::Standard).unwrap(),
254 ];
255 for (i, datetime) in datetimes.iter().enumerate() {
256 println!("{}", result[i]);
257 let expected_ymd_hms = datetime.ymd_hms().unwrap();
258 let result_ymd_hms = result[i].ymd_hms().unwrap();
259 assert_eq!(expected_ymd_hms, result_ymd_hms);
260 }
261 }
262 }