tank_tests/
time.rs

1use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
2use std::sync::LazyLock;
3use tank::{AsValue, Entity, Executor, QueryBuilder, 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 = executor
187        .prepare(
188            QueryBuilder::new()
189                .select(cols!(Times::timestamp_1 DESC))
190                .from(Times::table())
191                .where_condition(expr!(Times::timestamp_2 > ?))
192                .build(&executor.driver()),
193        )
194        .await
195        .expect("Could not prepare the query timestamp 1");
196    query_timestamp_1
197        .bind(PrimitiveDateTime::new(
198            Date::from_calendar_date(1999, Month::December, 31).unwrap(),
199            Time::from_hms(23, 59, 59).unwrap(),
200        ))
201        .expect("Could not bind the timestamp 1");
202    let values = executor
203        .fetch(&mut query_timestamp_1)
204        .and_then(|v| async {
205            PrimitiveDateTime::try_from_value(
206                v.values
207                    .into_iter()
208                    .next()
209                    .expect("Could not get the first column"),
210            )
211            .map(|v| v.to_string())
212        })
213        .try_collect::<Vec<_>>()
214        .await
215        .expect("Could not collect the values from the stream");
216    assert_eq!(
217        values,
218        [
219            "2050-11-11 18:45:59.0",
220            "2050-09-09 0:00:00.0",
221            "2038-01-19 3:14:07.0",
222            "2025-07-19 9:42:00.0",
223            "2025-01-01 0:00:00.0",
224        ]
225    );
226    query_timestamp_1
227        .clear_bindings()
228        .expect("Could not clear the bindings for query timestamp 1");
229    query_timestamp_1
230        .bind(PrimitiveDateTime::new(
231            Date::from_calendar_date(1800, Month::January, 1).unwrap(),
232            Time::from_hms(0, 0, 0).unwrap(),
233        ))
234        .expect("Could not bind the timestamp 1");
235    let values = executor
236        .fetch(&mut query_timestamp_1)
237        .and_then(|v| async {
238            NaiveDateTime::try_from_value(
239                v.values
240                    .into_iter()
241                    .next()
242                    .expect("Could not get the first column"),
243            )
244            .map(|v| v.to_string())
245        })
246        .try_collect::<Vec<_>>()
247        .await
248        .expect("Could not collect the values from the stream");
249    assert_eq!(
250        values,
251        [
252            "2050-11-11 18:45:59",
253            "2050-09-09 00:00:00",
254            "2038-01-19 03:14:07",
255            "2025-07-19 09:42:00",
256            "2025-01-01 00:00:00",
257            "1999-12-31 23:59:00",
258            "1987-10-05 14:09:00",
259            "1980-01-01 00:00:00",
260            "1950-06-15 08:30:00",
261        ]
262    );
263
264    // Query timestamp 2
265    let mut query_timestamp_2 = executor
266        .prepare(
267            QueryBuilder::new()
268                .select(cols!(Times::timestamp_2 ASC))
269                .from(Times::table())
270                .where_condition(expr!(Times::timestamp_1 <= ?))
271                .build(&executor.driver()),
272        )
273        .await
274        .expect("Could not prepare the query timestamp 1");
275    query_timestamp_2
276        .bind(NaiveDateTime::new(
277            NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
278            NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
279        ))
280        .expect("Could not bind the timestamp 1");
281    let values = executor
282        .fetch(&mut query_timestamp_2)
283        .and_then(|v| async {
284            NaiveDateTime::try_from_value(
285                v.values
286                    .into_iter()
287                    .next()
288                    .expect("Could not get the first column"),
289            )
290            .map(|v| v.to_string())
291        })
292        .try_collect::<Vec<_>>()
293        .await
294        .expect("Could not collect the values from the stream");
295    assert_eq!(
296        values,
297        [
298            "1950-06-15 08:30:00",
299            "1980-01-01 00:00:00",
300            "1987-10-05 14:09:00",
301            "1999-12-31 23:59:00",
302            "2025-01-01 00:00:00",
303        ]
304    );
305
306    // Query time 1
307    let mut query_time_1 = executor
308        .prepare(
309            QueryBuilder::new()
310                .select(cols!(Times::time_1 DESC))
311                .from(Times::table())
312                .where_condition(true)
313                .build(&executor.driver()),
314        )
315        .await
316        .expect("Could not prepare the query timestamp 1");
317    let values = executor
318        .fetch(&mut query_time_1)
319        .and_then(|v| async {
320            NaiveTime::try_from_value(
321                v.values
322                    .into_iter()
323                    .next()
324                    .expect("Could not get the first column"),
325            )
326            .map(|v| v.to_string())
327        })
328        .try_collect::<Vec<_>>()
329        .await
330        .expect("Could not collect the values from the stream");
331    assert_eq!(
332        values,
333        [
334            "23:59:00", "18:45:59", "14:09:00", "09:42:00", "08:30:00", "03:14:07", "00:00:00",
335            "00:00:00", "00:00:00",
336        ]
337    );
338}