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