1use crate::{
4 calendars::Calendar,
5 datetime::CFDatetime,
6 utils::{get_datetime_and_unit_from_units, unit_to_encode},
7};
8
9pub trait CFEncoder<T> {
12 fn encode_cf(&self, units: &str, calendar: Calendar) -> Result<T, crate::errors::Error>;
23}
24
25macro_rules! impl_cf_encoder {
26 ($type:ty) => {
27 impl CFEncoder<$type> for CFDatetime {
28 fn encode_cf(
29 &self,
30 units: &str,
31 calendar: Calendar,
32 ) -> Result<$type, crate::errors::Error> {
33 let (cf_datetime, unit) = get_datetime_and_unit_from_units(units, calendar)?;
34 let duration = (self - cf_datetime)?;
35 let result = unit_to_encode(&unit, duration);
36 Ok(result as $type)
37 }
38 }
39 };
40}
41
42impl_cf_encoder!(i64);
43impl_cf_encoder!(i32);
44impl_cf_encoder!(f32);
45impl_cf_encoder!(f64);
46
47macro_rules! impl_vec_cf_encoder {
48 ($type:ty) => {
49 impl CFEncoder<Vec<$type>> for Vec<CFDatetime> {
50 fn encode_cf(
51 &self,
52 units: &str,
53 calendar: Calendar,
54 ) -> Result<Vec<$type>, crate::errors::Error> {
55 let (cf_datetime, unit) = get_datetime_and_unit_from_units(units, calendar)?;
56 let mut result: Vec<$type> = Vec::with_capacity(self.len());
57 for datetime in self {
58 let duration = (datetime - &cf_datetime)?;
59 result.push(unit_to_encode(&unit, duration) as $type);
60 }
61 Ok(result)
62 }
63 }
64 };
65}
66
67impl_vec_cf_encoder!(i64);
68impl_vec_cf_encoder!(i32);
69impl_vec_cf_encoder!(f32);
70impl_vec_cf_encoder!(f64);
71
72macro_rules! impl_vec_ref_cf_encoder {
73 ($type:ty) => {
74 impl CFEncoder<Vec<$type>> for Vec<&CFDatetime> {
75 fn encode_cf(
76 &self,
77 units: &str,
78 calendar: Calendar,
79 ) -> Result<Vec<$type>, crate::errors::Error> {
80 let (cf_datetime, unit) = get_datetime_and_unit_from_units(units, calendar)?;
81 let mut result: Vec<$type> = Vec::with_capacity(self.len());
82 for datetime in self {
83 let duration = (*datetime - &cf_datetime)?;
84 result.push(unit_to_encode(&unit, duration) as $type);
85 }
86 Ok(result)
87 }
88 }
89 };
90}
91
92impl_vec_ref_cf_encoder!(i64);
93impl_vec_ref_cf_encoder!(i32);
94impl_vec_ref_cf_encoder!(f32);
95impl_vec_ref_cf_encoder!(f64);
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn test_encode_cf() {
103 let datetime = CFDatetime::from_ymd(2000, 1, 1, Calendar::Standard).unwrap();
104 let result: i64 = datetime
105 .encode_cf("seconds since 2000-01-01 00:00:00", Calendar::Standard)
106 .unwrap();
107 assert_eq!(result, 0);
108 let datetime = CFDatetime::from_ymd(2023, 1, 1, Calendar::Standard).unwrap();
109 let result: i64 = datetime
110 .encode_cf("seconds since 1970-01-01 00:00:00", Calendar::Standard)
111 .unwrap();
112 assert_eq!(result, 1672531200);
113 }
114 #[test]
115 fn test_vec_encode_cf() {
116 let datetimes = vec![
117 CFDatetime::from_ymd(2000, 1, 1, Calendar::Standard).unwrap(),
118 CFDatetime::from_ymd(2000, 1, 2, Calendar::Standard).unwrap(),
119 CFDatetime::from_ymd(2000, 1, 3, Calendar::Standard).unwrap(),
120 ];
121 let result: Vec<i64> = datetimes
122 .encode_cf("seconds since 2000-01-01 00:00:00", Calendar::Standard)
123 .unwrap();
124 assert_eq!(result, vec![0, 86400, 172800]);
125 }
126 #[test]
127 fn test_vec_encode_cf_days() {
128 let units = "days since 0000-01-01 00:00:00";
129 let datetimes = vec![
130 CFDatetime::from_ymd_hms(2000, 1, 1, 0, 0, 0.0, Calendar::Standard).unwrap(),
131 CFDatetime::from_ymd_hms(2000, 1, 2, 1, 0, 0.0, Calendar::Standard).unwrap(),
132 CFDatetime::from_ymd_hms(2000, 1, 3, 2, 0, 0.0, Calendar::Standard).unwrap(),
133 ];
134 let result: Vec<f64> = datetimes.encode_cf(units, Calendar::Standard).unwrap();
135 assert_eq!(result, vec![730487.0, 730488.0416666666, 730489.0833333334]);
136 }
137}