tank_tests/
time.rs

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    // Setup
23    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    // Insert times
31    let timestamps = [
32        // 1980-01-01 00:00:00
33        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        // 1987-10-05 14:09:00
48        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        // 1999-12-31 23:59:00
63        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        // 2025-01-01 00:00:00
78        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        // 1950-06-15 08:30:00
93        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        // 2038-01-19 03:14:07
108        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        // 2025-07-19 09:42:00
123        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        // 2050-11-11 18:45:59
138        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        // 2050-09-09 00:00:00
153        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, &timestamps)
170        .await
171        .expect("Failed to insert timestamps");
172
173    /*
174     * 1987-10-05 14:09:00
175     * 1999-12-31 23:59:00
176     * 2025-01-01 00:00:00
177     * 1950-06-15 08:30:00
178     * 1900-01-01 00:00:00
179     * 2038-01-19 03:14:07
180     * 2025-07-19 09:42:00
181     * 2050-11-11 18:45:59
182     * 2050-09-09 00:00:00
183     */
184
185    // Query timestamp 1
186    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    // Query timestamp 2
264    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    // Query time 1
305    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}