gitql_core/values/
datetime.rs1use std::any::Any;
2use std::cmp::Ordering;
3
4use super::base::Value;
5use super::boolean::BoolValue;
6use super::date::DateValue;
7
8use chrono::DateTime;
9use gitql_ast::operator::GroupComparisonOperator;
10use gitql_ast::types::datetime::DateTimeType;
11use gitql_ast::types::DataType;
12
13const VALUE_DATE_TIME_FORMAT: &str = "%Y-%m-%d %H:%M:%S%.3f";
14
15#[derive(Clone)]
16pub struct DateTimeValue {
17 pub value: i64,
18}
19
20impl DateTimeValue {
21 pub fn new(timestamp: i64) -> Self {
22 DateTimeValue { value: timestamp }
23 }
24}
25
26impl Value for DateTimeValue {
27 fn literal(&self) -> String {
28 let datetime = DateTime::from_timestamp(self.value, 0).unwrap();
29 format!("{}", datetime.format(VALUE_DATE_TIME_FORMAT))
30 }
31
32 fn equals(&self, other: &Box<dyn Value>) -> bool {
33 if let Some(other_datetime) = other.as_any().downcast_ref::<DateTimeValue>() {
34 return self.value == other_datetime.value;
35 }
36 false
37 }
38
39 fn compare(&self, other: &Box<dyn Value>) -> Option<Ordering> {
40 if let Some(other_datetime) = other.as_any().downcast_ref::<DateTimeValue>() {
41 return self.value.partial_cmp(&other_datetime.value);
42 }
43 None
44 }
45
46 fn data_type(&self) -> Box<dyn DataType> {
47 Box::new(DateTimeType)
48 }
49
50 fn as_any(&self) -> &dyn Any {
51 self
52 }
53
54 fn eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
55 if let Some(other_text) = other.as_any().downcast_ref::<DateTimeValue>() {
56 let are_equals = self.value == other_text.value;
57 return Ok(Box::new(BoolValue { value: are_equals }));
58 }
59 Err("Unexpected type to perform `=` with".to_string())
60 }
61
62 fn group_eq_op(
63 &self,
64 other: &Box<dyn Value>,
65 group_op: &GroupComparisonOperator,
66 ) -> Result<Box<dyn Value>, String> {
67 if other.is_array_of(|element_type| element_type.is_date_time()) {
68 let elements = &other.as_array().unwrap();
69 let mut matches_count = 0;
70 for element in elements.iter() {
71 if self.value == element.as_date_time().unwrap() {
72 matches_count += 1;
73 if GroupComparisonOperator::Any.eq(group_op) {
74 break;
75 }
76 }
77 }
78
79 let result = match group_op {
80 GroupComparisonOperator::All => matches_count == elements.len(),
81 GroupComparisonOperator::Any => matches_count > 0,
82 };
83
84 return Ok(Box::new(BoolValue::new(result)));
85 }
86 Err("Unexpected type to perform `=` with".to_string())
87 }
88
89 fn bang_eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
90 if let Some(other_text) = other.as_any().downcast_ref::<DateTimeValue>() {
91 let are_equals = self.value != other_text.value;
92 return Ok(Box::new(BoolValue { value: are_equals }));
93 }
94 Err("Unexpected type to perform `!=` with".to_string())
95 }
96
97 fn group_bang_eq_op(
98 &self,
99 other: &Box<dyn Value>,
100 group_op: &GroupComparisonOperator,
101 ) -> Result<Box<dyn Value>, String> {
102 if other.is_array_of(|element_type| element_type.is_date_time()) {
103 let elements = &other.as_array().unwrap();
104 let mut matches_count = 0;
105 for element in elements.iter() {
106 if self.value != element.as_date_time().unwrap() {
107 matches_count += 1;
108 if GroupComparisonOperator::Any.eq(group_op) {
109 break;
110 }
111 }
112 }
113
114 let result = match group_op {
115 GroupComparisonOperator::All => matches_count == elements.len(),
116 GroupComparisonOperator::Any => matches_count > 0,
117 };
118
119 return Ok(Box::new(BoolValue::new(result)));
120 }
121 Err("Unexpected type to perform `!=` with".to_string())
122 }
123
124 fn gt_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
125 if let Some(other_text) = other.as_any().downcast_ref::<DateTimeValue>() {
126 let are_equals = self.value > other_text.value;
127 return Ok(Box::new(BoolValue { value: are_equals }));
128 }
129 Err("Unexpected type to perform `>` with".to_string())
130 }
131
132 fn group_gt_op(
133 &self,
134 other: &Box<dyn Value>,
135 group_op: &GroupComparisonOperator,
136 ) -> Result<Box<dyn Value>, String> {
137 if other.is_array_of(|element_type| element_type.is_date_time()) {
138 let elements = &other.as_array().unwrap();
139 let mut matches_count = 0;
140 for element in elements.iter() {
141 if self.value > element.as_date_time().unwrap() {
142 matches_count += 1;
143 if GroupComparisonOperator::Any.eq(group_op) {
144 break;
145 }
146 }
147 }
148
149 let result = match group_op {
150 GroupComparisonOperator::All => matches_count == elements.len(),
151 GroupComparisonOperator::Any => matches_count > 0,
152 };
153
154 return Ok(Box::new(BoolValue::new(result)));
155 }
156 Err("Unexpected type to perform `>` with".to_string())
157 }
158
159 fn gte_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
160 if let Some(other_text) = other.as_any().downcast_ref::<DateTimeValue>() {
161 let are_equals = self.value >= other_text.value;
162 return Ok(Box::new(BoolValue { value: are_equals }));
163 }
164 Err("Unexpected type to perform `>=` with".to_string())
165 }
166
167 fn group_gte_op(
168 &self,
169 other: &Box<dyn Value>,
170 group_op: &GroupComparisonOperator,
171 ) -> Result<Box<dyn Value>, String> {
172 if other.is_array_of(|element_type| element_type.is_date_time()) {
173 let elements = &other.as_array().unwrap();
174 let mut matches_count = 0;
175 for element in elements.iter() {
176 if self.value >= element.as_date_time().unwrap() {
177 matches_count += 1;
178 if GroupComparisonOperator::Any.eq(group_op) {
179 break;
180 }
181 }
182 }
183
184 let result = match group_op {
185 GroupComparisonOperator::All => matches_count == elements.len(),
186 GroupComparisonOperator::Any => matches_count > 0,
187 };
188
189 return Ok(Box::new(BoolValue::new(result)));
190 }
191 Err("Unexpected type to perform `>=` with".to_string())
192 }
193
194 fn lt_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
195 if let Some(other_text) = other.as_any().downcast_ref::<DateTimeValue>() {
196 let are_equals = self.value < other_text.value;
197 return Ok(Box::new(BoolValue { value: are_equals }));
198 }
199 Err("Unexpected type to perform `<` with".to_string())
200 }
201
202 fn group_lt_op(
203 &self,
204 other: &Box<dyn Value>,
205 group_op: &GroupComparisonOperator,
206 ) -> Result<Box<dyn Value>, String> {
207 if other.is_array_of(|element_type| element_type.is_date_time()) {
208 let elements = &other.as_array().unwrap();
209 let mut matches_count = 0;
210 for element in elements.iter() {
211 if self.value < element.as_date_time().unwrap() {
212 matches_count += 1;
213 if GroupComparisonOperator::Any.eq(group_op) {
214 break;
215 }
216 }
217 }
218
219 let result = match group_op {
220 GroupComparisonOperator::All => matches_count == elements.len(),
221 GroupComparisonOperator::Any => matches_count > 0,
222 };
223
224 return Ok(Box::new(BoolValue::new(result)));
225 }
226 Err("Unexpected type to perform `<` with".to_string())
227 }
228
229 fn lte_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
230 if let Some(other_text) = other.as_any().downcast_ref::<DateTimeValue>() {
231 let are_equals = self.value <= other_text.value;
232 return Ok(Box::new(BoolValue { value: are_equals }));
233 }
234 Err("Unexpected type to perform `<=` with".to_string())
235 }
236
237 fn group_lte_op(
238 &self,
239 other: &Box<dyn Value>,
240 group_op: &GroupComparisonOperator,
241 ) -> Result<Box<dyn Value>, String> {
242 if other.is_array_of(|element_type| element_type.is_date_time()) {
243 let elements = &other.as_array().unwrap();
244 let mut matches_count = 0;
245 for element in elements.iter() {
246 if self.value <= element.as_date_time().unwrap() {
247 matches_count += 1;
248 if GroupComparisonOperator::Any.eq(group_op) {
249 break;
250 }
251 }
252 }
253
254 let result = match group_op {
255 GroupComparisonOperator::All => matches_count == elements.len(),
256 GroupComparisonOperator::Any => matches_count > 0,
257 };
258
259 return Ok(Box::new(BoolValue::new(result)));
260 }
261 Err("Unexpected type to perform `<=` with".to_string())
262 }
263
264 fn cast_op(&self, target_type: &Box<dyn DataType>) -> Result<Box<dyn Value>, String> {
265 if target_type.is_date() {
266 return Ok(Box::new(DateValue {
267 timestamp: self.value,
268 }));
269 }
270 Err("Unexpected type to perform `Cast` with".to_string())
271 }
272}