Skip to main content

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