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