1use std::ptr;
5
6use reifydb_value::{
7 reifydb_assertions,
8 value::{datetime::DateTime, value_type::ValueType},
9};
10
11use crate::encoded::{row::EncodedRow, shape::RowShape};
12
13impl RowShape {
14 pub fn set_datetime(&self, row: &mut EncodedRow, index: usize, value: DateTime) {
15 let field = &self.fields()[index];
16 reifydb_assertions! {
17 assert!(
18 row.len() >= self.total_static_size(),
19 "row/shape size mismatch: row.len()={} < total_static_size()={}",
20 row.len(),
21 self.total_static_size()
22 );
23 assert_eq!(*field.constraint.get_type().inner_type(), ValueType::DateTime);
24 }
25 row.set_valid(index, true);
26
27 let nanos = value.to_nanos();
28 unsafe {
29 ptr::write_unaligned(row.make_mut().as_mut_ptr().add(field.offset as usize) as *mut u64, nanos);
30 }
31 }
32
33 pub fn get_datetime(&self, row: &EncodedRow, index: usize) -> DateTime {
34 let field = &self.fields()[index];
35 reifydb_assertions! {
36 assert!(
37 row.len() >= self.total_static_size(),
38 "row/shape size mismatch: row.len()={} < total_static_size()={}",
39 row.len(),
40 self.total_static_size()
41 );
42 assert_eq!(*field.constraint.get_type().inner_type(), ValueType::DateTime);
43 }
44 unsafe {
45 let nanos = (row.as_ptr().add(field.offset as usize) as *const u64).read_unaligned();
46 DateTime::from_nanos(nanos)
47 }
48 }
49
50 pub fn try_get_datetime(&self, row: &EncodedRow, index: usize) -> Option<DateTime> {
51 if row.is_defined(index) && self.fields()[index].constraint.get_type() == ValueType::DateTime {
52 Some(self.get_datetime(row, index))
53 } else {
54 None
55 }
56 }
57}
58
59#[cfg(test)]
60pub mod tests {
61 use reifydb_value::value::{datetime::DateTime, value_type::ValueType};
62
63 use crate::encoded::shape::RowShape;
64
65 #[test]
66 fn test_set_get_datetime() {
67 let shape = RowShape::testing(&[ValueType::DateTime]);
68 let mut row = shape.allocate();
69
70 let value = DateTime::new(2024, 9, 9, 08, 17, 0, 1234).unwrap();
71 shape.set_datetime(&mut row, 0, value.clone());
72 assert_eq!(shape.get_datetime(&row, 0), value);
73 }
74
75 #[test]
76 fn test_try_get_datetime() {
77 let shape = RowShape::testing(&[ValueType::DateTime]);
78 let mut row = shape.allocate();
79
80 assert_eq!(shape.try_get_datetime(&row, 0), None);
81
82 let test_datetime = DateTime::from_timestamp(1642694400).unwrap();
83 shape.set_datetime(&mut row, 0, test_datetime.clone());
84 assert_eq!(shape.try_get_datetime(&row, 0), Some(test_datetime));
85 }
86
87 #[test]
88 fn test_epoch() {
89 let shape = RowShape::testing(&[ValueType::DateTime]);
90 let mut row = shape.allocate();
91
92 let epoch = DateTime::default(); shape.set_datetime(&mut row, 0, epoch.clone());
94 assert_eq!(shape.get_datetime(&row, 0), epoch);
95 }
96
97 #[test]
98 fn test_with_nanoseconds() {
99 let shape = RowShape::testing(&[ValueType::DateTime]);
100 let mut row = shape.allocate();
101
102 let precise_datetime = DateTime::new(2024, 12, 25, 15, 30, 45, 123456789).unwrap();
104 shape.set_datetime(&mut row, 0, precise_datetime.clone());
105 assert_eq!(shape.get_datetime(&row, 0), precise_datetime);
106 }
107
108 #[test]
109 fn test_various_timestamps() {
110 let shape = RowShape::testing(&[ValueType::DateTime]);
111
112 let test_datetimes = [
113 DateTime::from_timestamp(0).unwrap(), DateTime::from_timestamp(946684800).unwrap(), DateTime::from_timestamp(1640995200).unwrap(), DateTime::from_timestamp(1735689600).unwrap(), ];
118
119 for datetime in test_datetimes {
120 let mut row = shape.allocate();
121 shape.set_datetime(&mut row, 0, datetime.clone());
122 assert_eq!(shape.get_datetime(&row, 0), datetime);
123 }
124 }
125
126 #[test]
127 fn test_mixed_with_other_types() {
128 let shape = RowShape::testing(&[
129 ValueType::DateTime,
130 ValueType::Boolean,
131 ValueType::DateTime,
132 ValueType::Int8,
133 ]);
134 let mut row = shape.allocate();
135
136 let datetime1 = DateTime::new(2025, 6, 15, 12, 0, 0, 0).unwrap();
137 let datetime2 = DateTime::new(1995, 3, 22, 18, 30, 45, 500000000).unwrap();
138
139 shape.set_datetime(&mut row, 0, datetime1.clone());
140 shape.set_bool(&mut row, 1, true);
141 shape.set_datetime(&mut row, 2, datetime2.clone());
142 shape.set_i64(&mut row, 3, 1234567890);
143
144 assert_eq!(shape.get_datetime(&row, 0), datetime1);
145 assert_eq!(shape.get_bool(&row, 1), true);
146 assert_eq!(shape.get_datetime(&row, 2), datetime2);
147 assert_eq!(shape.get_i64(&row, 3), 1234567890);
148 }
149
150 #[test]
151 fn test_undefined_handling() {
152 let shape = RowShape::testing(&[ValueType::DateTime, ValueType::DateTime]);
153 let mut row = shape.allocate();
154
155 let datetime = DateTime::new(2025, 7, 4, 16, 20, 15, 750000000).unwrap();
156 shape.set_datetime(&mut row, 0, datetime.clone());
157
158 assert_eq!(shape.try_get_datetime(&row, 0), Some(datetime));
159 assert_eq!(shape.try_get_datetime(&row, 1), None);
160
161 shape.set_none(&mut row, 0);
162 assert_eq!(shape.try_get_datetime(&row, 0), None);
163 }
164
165 #[test]
166 fn test_precision_preservation() {
167 let shape = RowShape::testing(&[ValueType::DateTime]);
168 let mut row = shape.allocate();
169
170 let high_precision = DateTime::new(2024, 1, 1, 0, 0, 0, 999999999).unwrap();
172 shape.set_datetime(&mut row, 0, high_precision.clone());
173
174 let retrieved = shape.get_datetime(&row, 0);
175 assert_eq!(retrieved, high_precision);
176
177 let orig_nanos = high_precision.to_nanos();
178 let ret_nanos = retrieved.to_nanos();
179 assert_eq!(orig_nanos, ret_nanos);
180 }
181
182 #[test]
183 fn test_year_2038_problem() {
184 let shape = RowShape::testing(&[ValueType::DateTime]);
185 let mut row = shape.allocate();
186
187 let post_2038 = DateTime::from_timestamp(2147483648).unwrap(); shape.set_datetime(&mut row, 0, post_2038.clone());
190 assert_eq!(shape.get_datetime(&row, 0), post_2038);
191 }
192
193 #[test]
194 fn test_far_future() {
195 let shape = RowShape::testing(&[ValueType::DateTime]);
196 let mut row = shape.allocate();
197
198 let far_future = DateTime::from_timestamp(4102444800).unwrap(); shape.set_datetime(&mut row, 0, far_future.clone());
201 assert_eq!(shape.get_datetime(&row, 0), far_future);
202 }
203
204 #[test]
205 fn test_microsecond_precision() {
206 let shape = RowShape::testing(&[ValueType::DateTime]);
207 let mut row = shape.allocate();
208
209 let microsecond_precision = DateTime::new(2024, 6, 15, 14, 30, 25, 123456000).unwrap();
211 shape.set_datetime(&mut row, 0, microsecond_precision.clone());
212 assert_eq!(shape.get_datetime(&row, 0), microsecond_precision);
213 }
214
215 #[test]
216 fn test_try_get_datetime_wrong_type() {
217 let shape = RowShape::testing(&[ValueType::Boolean]);
218 let mut row = shape.allocate();
219
220 shape.set_bool(&mut row, 0, true);
221
222 assert_eq!(shape.try_get_datetime(&row, 0), None);
223 }
224}