1use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
2use std::sync::LazyLock;
3use tank::{AsValue, DataSet, Entity, Executor, cols, expr, stream::TryStreamExt};
4use time::{Date, Month, PrimitiveDateTime, Time};
5use tokio::sync::Mutex;
6
7static MUTEX: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
8
9#[derive(Entity, Debug, Clone, PartialEq, Eq, Hash)]
10pub struct Times {
11 pub timestamp_1: PrimitiveDateTime,
12 pub timestamp_2: chrono::NaiveDateTime,
13 pub date_1: Date,
14 pub date_2: NaiveDate,
15 pub time_1: time::Time,
16 pub time_2: NaiveTime,
17}
18
19pub async fn times<E: Executor>(executor: &mut E) {
20 let _lock = MUTEX.lock().await;
21
22 Times::drop_table(executor, true, false)
24 .await
25 .expect("Failed to drop Times table");
26 Times::create_table(executor, false, true)
27 .await
28 .expect("Failed to create Times table");
29
30 let timestamps = [
32 Times {
34 timestamp_1: PrimitiveDateTime::new(
35 Date::from_calendar_date(1980, Month::January, 1).unwrap(),
36 Time::from_hms(0, 0, 0).unwrap(),
37 ),
38 timestamp_2: NaiveDateTime::new(
39 NaiveDate::from_ymd_opt(1980, 1, 1).unwrap(),
40 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
41 ),
42 date_1: Date::from_calendar_date(1980, Month::January, 1).unwrap(),
43 date_2: NaiveDate::from_ymd_opt(1980, 1, 1).unwrap(),
44 time_1: Time::from_hms(0, 0, 0).unwrap(),
45 time_2: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
46 },
47 Times {
49 timestamp_1: PrimitiveDateTime::new(
50 Date::from_calendar_date(1987, Month::October, 5).unwrap(),
51 Time::from_hms(14, 9, 0).unwrap(),
52 ),
53 timestamp_2: NaiveDateTime::new(
54 NaiveDate::from_ymd_opt(1987, 10, 5).unwrap(),
55 NaiveTime::from_hms_opt(14, 9, 0).unwrap(),
56 ),
57 date_1: Date::from_calendar_date(1987, Month::October, 5).unwrap(),
58 date_2: NaiveDate::from_ymd_opt(1987, 10, 5).unwrap(),
59 time_1: Time::from_hms(14, 9, 0).unwrap(),
60 time_2: NaiveTime::from_hms_opt(14, 9, 0).unwrap(),
61 },
62 Times {
64 timestamp_1: PrimitiveDateTime::new(
65 Date::from_calendar_date(1999, Month::December, 31).unwrap(),
66 Time::from_hms(23, 59, 0).unwrap(),
67 ),
68 timestamp_2: NaiveDateTime::new(
69 NaiveDate::from_ymd_opt(1999, 12, 31).unwrap(),
70 NaiveTime::from_hms_opt(23, 59, 0).unwrap(),
71 ),
72 date_1: Date::from_calendar_date(1999, Month::December, 31).unwrap(),
73 date_2: NaiveDate::from_ymd_opt(1999, 12, 31).unwrap(),
74 time_1: Time::from_hms(23, 59, 0).unwrap(),
75 time_2: NaiveTime::from_hms_opt(23, 59, 0).unwrap(),
76 },
77 Times {
79 timestamp_1: PrimitiveDateTime::new(
80 Date::from_calendar_date(2025, Month::January, 1).unwrap(),
81 Time::from_hms(0, 0, 0).unwrap(),
82 ),
83 timestamp_2: NaiveDateTime::new(
84 NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
85 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
86 ),
87 date_1: Date::from_calendar_date(2025, Month::January, 1).unwrap(),
88 date_2: NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
89 time_1: Time::from_hms(0, 0, 0).unwrap(),
90 time_2: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
91 },
92 Times {
94 timestamp_1: PrimitiveDateTime::new(
95 Date::from_calendar_date(1950, Month::June, 15).unwrap(),
96 Time::from_hms(8, 30, 0).unwrap(),
97 ),
98 timestamp_2: NaiveDateTime::new(
99 NaiveDate::from_ymd_opt(1950, 6, 15).unwrap(),
100 NaiveTime::from_hms_opt(8, 30, 0).unwrap(),
101 ),
102 date_1: Date::from_calendar_date(1950, Month::June, 15).unwrap(),
103 date_2: NaiveDate::from_ymd_opt(1950, 6, 15).unwrap(),
104 time_1: Time::from_hms(8, 30, 0).unwrap(),
105 time_2: NaiveTime::from_hms_opt(8, 30, 0).unwrap(),
106 },
107 Times {
109 timestamp_1: PrimitiveDateTime::new(
110 Date::from_calendar_date(2038, Month::January, 19).unwrap(),
111 Time::from_hms(3, 14, 7).unwrap(),
112 ),
113 timestamp_2: NaiveDateTime::new(
114 NaiveDate::from_ymd_opt(2038, 1, 19).unwrap(),
115 NaiveTime::from_hms_opt(3, 14, 7).unwrap(),
116 ),
117 date_1: Date::from_calendar_date(2038, Month::January, 19).unwrap(),
118 date_2: NaiveDate::from_ymd_opt(2038, 1, 19).unwrap(),
119 time_1: Time::from_hms(3, 14, 7).unwrap(),
120 time_2: NaiveTime::from_hms_opt(3, 14, 7).unwrap(),
121 },
122 Times {
124 timestamp_1: PrimitiveDateTime::new(
125 Date::from_calendar_date(2025, Month::July, 19).unwrap(),
126 Time::from_hms(9, 42, 0).unwrap(),
127 ),
128 timestamp_2: NaiveDateTime::new(
129 NaiveDate::from_ymd_opt(2025, 7, 19).unwrap(),
130 NaiveTime::from_hms_opt(9, 42, 0).unwrap(),
131 ),
132 date_1: Date::from_calendar_date(2025, Month::July, 19).unwrap(),
133 date_2: NaiveDate::from_ymd_opt(2025, 7, 19).unwrap(),
134 time_1: Time::from_hms(9, 42, 0).unwrap(),
135 time_2: NaiveTime::from_hms_opt(9, 42, 0).unwrap(),
136 },
137 Times {
139 timestamp_1: PrimitiveDateTime::new(
140 Date::from_calendar_date(2050, Month::November, 11).unwrap(),
141 Time::from_hms(18, 45, 59).unwrap(),
142 ),
143 timestamp_2: NaiveDateTime::new(
144 NaiveDate::from_ymd_opt(2050, 11, 11).unwrap(),
145 NaiveTime::from_hms_opt(18, 45, 59).unwrap(),
146 ),
147 date_1: Date::from_calendar_date(2050, Month::November, 11).unwrap(),
148 date_2: NaiveDate::from_ymd_opt(2050, 11, 11).unwrap(),
149 time_1: Time::from_hms(18, 45, 59).unwrap(),
150 time_2: NaiveTime::from_hms_opt(18, 45, 59).unwrap(),
151 },
152 Times {
154 timestamp_1: PrimitiveDateTime::new(
155 Date::from_calendar_date(2050, Month::September, 9).unwrap(),
156 Time::from_hms(0, 0, 0).unwrap(),
157 ),
158 timestamp_2: NaiveDateTime::new(
159 NaiveDate::from_ymd_opt(2050, 9, 9).unwrap(),
160 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
161 ),
162 date_1: Date::from_calendar_date(2050, Month::September, 9).unwrap(),
163 date_2: NaiveDate::from_ymd_opt(2050, 9, 9).unwrap(),
164 time_1: Time::from_hms(0, 0, 0).unwrap(),
165 time_2: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
166 },
167 ];
168
169 Times::insert_many(executor, ×tamps)
170 .await
171 .expect("Failed to insert timestamps");
172
173 let mut query_timestamp_1 = Times::table()
187 .prepare(
188 executor,
189 cols!(Times::timestamp_1 DESC),
190 &expr!(Times::timestamp_2 > ?),
191 None,
192 )
193 .await
194 .expect("Could not prepare the query timestamp 1");
195 query_timestamp_1
196 .bind(PrimitiveDateTime::new(
197 Date::from_calendar_date(1999, Month::December, 31).unwrap(),
198 Time::from_hms(23, 59, 59).unwrap(),
199 ))
200 .expect("Could not bind the timestamp 1");
201 let values = executor
202 .fetch(&mut query_timestamp_1)
203 .and_then(|v| async {
204 PrimitiveDateTime::try_from_value(
205 v.values
206 .into_iter()
207 .next()
208 .expect("Could not get the first column"),
209 )
210 .map(|v| v.to_string())
211 })
212 .try_collect::<Vec<_>>()
213 .await
214 .expect("Could not collect the values from the stream");
215 assert_eq!(
216 values,
217 [
218 "2050-11-11 18:45:59.0",
219 "2050-09-09 0:00:00.0",
220 "2038-01-19 3:14:07.0",
221 "2025-07-19 9:42:00.0",
222 "2025-01-01 0:00:00.0",
223 ]
224 );
225 query_timestamp_1
226 .clear_bindings()
227 .expect("Could not clear the bindings for query timestamp 1");
228 query_timestamp_1
229 .bind(PrimitiveDateTime::new(
230 Date::from_calendar_date(1800, Month::January, 1).unwrap(),
231 Time::from_hms(0, 0, 0).unwrap(),
232 ))
233 .expect("Could not bind the timestamp 1");
234 let values = executor
235 .fetch(&mut query_timestamp_1)
236 .and_then(|v| async {
237 NaiveDateTime::try_from_value(
238 v.values
239 .into_iter()
240 .next()
241 .expect("Could not get the first column"),
242 )
243 .map(|v| v.to_string())
244 })
245 .try_collect::<Vec<_>>()
246 .await
247 .expect("Could not collect the values from the stream");
248 assert_eq!(
249 values,
250 [
251 "2050-11-11 18:45:59",
252 "2050-09-09 00:00:00",
253 "2038-01-19 03:14:07",
254 "2025-07-19 09:42:00",
255 "2025-01-01 00:00:00",
256 "1999-12-31 23:59:00",
257 "1987-10-05 14:09:00",
258 "1980-01-01 00:00:00",
259 "1950-06-15 08:30:00",
260 ]
261 );
262
263 let mut query_timestamp_2 = Times::table()
265 .prepare(
266 executor,
267 cols!(Times::timestamp_2 ASC),
268 &expr!(Times::timestamp_1 <= ?),
269 None,
270 )
271 .await
272 .expect("Could not prepare the query timestamp 1");
273 query_timestamp_2
274 .bind(NaiveDateTime::new(
275 NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
276 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
277 ))
278 .expect("Could not bind the timestamp 1");
279 let values = executor
280 .fetch(&mut query_timestamp_2)
281 .and_then(|v| async {
282 NaiveDateTime::try_from_value(
283 v.values
284 .into_iter()
285 .next()
286 .expect("Could not get the first column"),
287 )
288 .map(|v| v.to_string())
289 })
290 .try_collect::<Vec<_>>()
291 .await
292 .expect("Could not collect the values from the stream");
293 assert_eq!(
294 values,
295 [
296 "1950-06-15 08:30:00",
297 "1980-01-01 00:00:00",
298 "1987-10-05 14:09:00",
299 "1999-12-31 23:59:00",
300 "2025-01-01 00:00:00",
301 ]
302 );
303
304 let mut query_time_1 = Times::table()
306 .prepare(executor, cols!(Times::time_1 DESC), &true, None)
307 .await
308 .expect("Could not prepare the query timestamp 1");
309 let values = executor
310 .fetch(&mut query_time_1)
311 .and_then(|v| async {
312 NaiveTime::try_from_value(
313 v.values
314 .into_iter()
315 .next()
316 .expect("Could not get the first column"),
317 )
318 .map(|v| v.to_string())
319 })
320 .try_collect::<Vec<_>>()
321 .await
322 .expect("Could not collect the values from the stream");
323 assert_eq!(
324 values,
325 [
326 "23:59:00", "18:45:59", "14:09:00", "09:42:00", "08:30:00", "03:14:07", "00:00:00",
327 "00:00:00", "00:00:00",
328 ]
329 );
330}