1use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
2use std::{
3 sync::LazyLock,
4 time::{SystemTime, UNIX_EPOCH},
5};
6use tank::{
7 AsValue, Entity, Executor, Operand, QueryBuilder, Result, cols, expr,
8 stream::{StreamExt, TryStreamExt},
9};
10use time::{Date, Month, PrimitiveDateTime, Time};
11use tokio::sync::Mutex;
12
13static MUTEX: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
14
15#[derive(Entity, Debug, Clone, PartialEq, Eq, Hash)]
16pub struct Times {
17 pub timestamp_1: PrimitiveDateTime,
18 pub timestamp_2: chrono::NaiveDateTime,
19 pub date_1: Date,
20 pub date_2: NaiveDate,
21 pub time_1: time::Time,
22 pub time_2: NaiveTime,
23}
24
25pub async fn times<E: Executor>(executor: &mut E) {
26 let _lock = MUTEX.lock().await;
27
28 Times::drop_table(executor, true, false)
30 .await
31 .expect("Failed to drop Times table");
32 Times::create_table(executor, false, true)
33 .await
34 .expect("Failed to create Times table");
35
36 let timestamps = [
38 Times {
40 timestamp_1: PrimitiveDateTime::new(
41 Date::from_calendar_date(1980, Month::January, 1).unwrap(),
42 Time::from_hms(0, 0, 0).unwrap(),
43 ),
44 timestamp_2: NaiveDateTime::new(
45 NaiveDate::from_ymd_opt(1980, 1, 1).unwrap(),
46 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
47 ),
48 date_1: Date::from_calendar_date(1980, Month::January, 1).unwrap(),
49 date_2: NaiveDate::from_ymd_opt(1980, 1, 1).unwrap(),
50 time_1: Time::from_hms(0, 0, 0).unwrap(),
51 time_2: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
52 },
53 Times {
55 timestamp_1: PrimitiveDateTime::new(
56 Date::from_calendar_date(1987, Month::October, 5).unwrap(),
57 Time::from_hms(14, 9, 0).unwrap(),
58 ),
59 timestamp_2: NaiveDateTime::new(
60 NaiveDate::from_ymd_opt(1987, 10, 5).unwrap(),
61 NaiveTime::from_hms_opt(14, 9, 0).unwrap(),
62 ),
63 date_1: Date::from_calendar_date(1987, Month::October, 5).unwrap(),
64 date_2: NaiveDate::from_ymd_opt(1987, 10, 5).unwrap(),
65 time_1: Time::from_hms(14, 9, 0).unwrap(),
66 time_2: NaiveTime::from_hms_opt(14, 9, 0).unwrap(),
67 },
68 Times {
70 timestamp_1: PrimitiveDateTime::new(
71 Date::from_calendar_date(1999, Month::December, 31).unwrap(),
72 Time::from_hms(23, 59, 0).unwrap(),
73 ),
74 timestamp_2: NaiveDateTime::new(
75 NaiveDate::from_ymd_opt(1999, 12, 31).unwrap(),
76 NaiveTime::from_hms_opt(23, 59, 0).unwrap(),
77 ),
78 date_1: Date::from_calendar_date(1999, Month::December, 31).unwrap(),
79 date_2: NaiveDate::from_ymd_opt(1999, 12, 31).unwrap(),
80 time_1: Time::from_hms(23, 59, 0).unwrap(),
81 time_2: NaiveTime::from_hms_opt(23, 59, 0).unwrap(),
82 },
83 Times {
85 timestamp_1: PrimitiveDateTime::new(
86 Date::from_calendar_date(2025, Month::January, 1).unwrap(),
87 Time::from_hms(0, 0, 0).unwrap(),
88 ),
89 timestamp_2: NaiveDateTime::new(
90 NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
91 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
92 ),
93 date_1: Date::from_calendar_date(2025, Month::January, 1).unwrap(),
94 date_2: NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
95 time_1: Time::from_hms(0, 0, 0).unwrap(),
96 time_2: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
97 },
98 Times {
100 timestamp_1: PrimitiveDateTime::new(
101 Date::from_calendar_date(1950, Month::June, 15).unwrap(),
102 Time::from_hms(8, 30, 0).unwrap(),
103 ),
104 timestamp_2: NaiveDateTime::new(
105 NaiveDate::from_ymd_opt(1950, 6, 15).unwrap(),
106 NaiveTime::from_hms_opt(8, 30, 0).unwrap(),
107 ),
108 date_1: Date::from_calendar_date(1950, Month::June, 15).unwrap(),
109 date_2: NaiveDate::from_ymd_opt(1950, 6, 15).unwrap(),
110 time_1: Time::from_hms(8, 30, 0).unwrap(),
111 time_2: NaiveTime::from_hms_opt(8, 30, 0).unwrap(),
112 },
113 Times {
115 timestamp_1: PrimitiveDateTime::new(
116 Date::from_calendar_date(2038, Month::January, 19).unwrap(),
117 Time::from_hms(3, 14, 7).unwrap(),
118 ),
119 timestamp_2: NaiveDateTime::new(
120 NaiveDate::from_ymd_opt(2038, 1, 19).unwrap(),
121 NaiveTime::from_hms_opt(3, 14, 7).unwrap(),
122 ),
123 date_1: Date::from_calendar_date(2038, Month::January, 19).unwrap(),
124 date_2: NaiveDate::from_ymd_opt(2038, 1, 19).unwrap(),
125 time_1: Time::from_hms(3, 14, 7).unwrap(),
126 time_2: NaiveTime::from_hms_opt(3, 14, 7).unwrap(),
127 },
128 Times {
130 timestamp_1: PrimitiveDateTime::new(
131 Date::from_calendar_date(2025, Month::July, 19).unwrap(),
132 Time::from_hms(9, 42, 0).unwrap(),
133 ),
134 timestamp_2: NaiveDateTime::new(
135 NaiveDate::from_ymd_opt(2025, 7, 19).unwrap(),
136 NaiveTime::from_hms_opt(9, 42, 0).unwrap(),
137 ),
138 date_1: Date::from_calendar_date(2025, Month::July, 19).unwrap(),
139 date_2: NaiveDate::from_ymd_opt(2025, 7, 19).unwrap(),
140 time_1: Time::from_hms(9, 42, 0).unwrap(),
141 time_2: NaiveTime::from_hms_opt(9, 42, 0).unwrap(),
142 },
143 Times {
145 timestamp_1: PrimitiveDateTime::new(
146 Date::from_calendar_date(2050, Month::November, 11).unwrap(),
147 Time::from_hms(18, 45, 59).unwrap(),
148 ),
149 timestamp_2: NaiveDateTime::new(
150 NaiveDate::from_ymd_opt(2050, 11, 11).unwrap(),
151 NaiveTime::from_hms_opt(18, 45, 59).unwrap(),
152 ),
153 date_1: Date::from_calendar_date(2050, Month::November, 11).unwrap(),
154 date_2: NaiveDate::from_ymd_opt(2050, 11, 11).unwrap(),
155 time_1: Time::from_hms(18, 45, 59).unwrap(),
156 time_2: NaiveTime::from_hms_opt(18, 45, 59).unwrap(),
157 },
158 Times {
160 timestamp_1: PrimitiveDateTime::new(
161 Date::from_calendar_date(2050, Month::September, 9).unwrap(),
162 Time::from_hms(0, 0, 0).unwrap(),
163 ),
164 timestamp_2: NaiveDateTime::new(
165 NaiveDate::from_ymd_opt(2050, 9, 9).unwrap(),
166 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
167 ),
168 date_1: Date::from_calendar_date(2050, Month::September, 9).unwrap(),
169 date_2: NaiveDate::from_ymd_opt(2050, 9, 9).unwrap(),
170 time_1: Time::from_hms(0, 0, 0).unwrap(),
171 time_2: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
172 },
173 ];
174
175 Times::insert_many(executor, ×tamps)
176 .await
177 .expect("Failed to insert timestamps");
178
179 let mut query_timestamp_1 = executor
193 .prepare(
194 QueryBuilder::new()
195 .select([Times::timestamp_1])
196 .from(Times::table())
197 .where_expr(expr!(Times::timestamp_2 > ?))
198 .order_by(cols!(Times::timestamp_1 DESC))
199 .build(&executor.driver()),
200 )
201 .await
202 .expect("Could not prepare the query timestamp 1");
203 query_timestamp_1
204 .bind(PrimitiveDateTime::new(
205 Date::from_calendar_date(1999, Month::December, 31).unwrap(),
206 Time::from_hms(23, 59, 59).unwrap(),
207 ))
208 .expect("Could not bind the timestamp 1");
209 let values = executor
210 .fetch(&mut query_timestamp_1)
211 .and_then(|v| async {
212 PrimitiveDateTime::try_from_value(
213 v.values
214 .into_iter()
215 .next()
216 .expect("Could not get the first column"),
217 )
218 .map(|v| v.to_string())
219 })
220 .try_collect::<Vec<_>>()
221 .await
222 .expect("Could not collect the values from the stream");
223 assert_eq!(
224 values,
225 [
226 "2050-11-11 18:45:59.0",
227 "2050-09-09 0:00:00.0",
228 "2038-01-19 3:14:07.0",
229 "2025-07-19 9:42:00.0",
230 "2025-01-01 0:00:00.0",
231 ]
232 );
233 query_timestamp_1
234 .clear_bindings()
235 .expect("Could not clear the bindings for query timestamp 1");
236 query_timestamp_1
237 .bind(PrimitiveDateTime::new(
238 Date::from_calendar_date(1800, Month::January, 1).unwrap(),
239 Time::from_hms(0, 0, 0).unwrap(),
240 ))
241 .expect("Could not bind the timestamp 1");
242 let values = executor
243 .fetch(&mut query_timestamp_1)
244 .and_then(|v| async {
245 NaiveDateTime::try_from_value(
246 v.values
247 .into_iter()
248 .next()
249 .expect("Could not get the first column"),
250 )
251 .map(|v| v.to_string())
252 })
253 .try_collect::<Vec<_>>()
254 .await
255 .expect("Could not collect the values from the stream");
256 assert_eq!(
257 values,
258 [
259 "2050-11-11 18:45:59",
260 "2050-09-09 00:00:00",
261 "2038-01-19 03:14:07",
262 "2025-07-19 09:42:00",
263 "2025-01-01 00:00:00",
264 "1999-12-31 23:59:00",
265 "1987-10-05 14:09:00",
266 "1980-01-01 00:00:00",
267 "1950-06-15 08:30:00",
268 ]
269 );
270
271 let mut query_timestamp_2 = executor
273 .prepare(
274 QueryBuilder::new()
275 .select([Times::timestamp_2])
276 .from(Times::table())
277 .where_expr(expr!(Times::timestamp_1 <= ?))
278 .order_by(cols!(Times::timestamp_2 ASC))
279 .build(&executor.driver()),
280 )
281 .await
282 .expect("Could not prepare the query timestamp 1");
283 query_timestamp_2
284 .bind(NaiveDateTime::new(
285 NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
286 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
287 ))
288 .expect("Could not bind the timestamp 1");
289 let values = executor
290 .fetch(&mut query_timestamp_2)
291 .and_then(|v| async {
292 NaiveDateTime::try_from_value(
293 v.values
294 .into_iter()
295 .next()
296 .expect("Could not get the first column"),
297 )
298 .map(|v| v.to_string())
299 })
300 .try_collect::<Vec<_>>()
301 .await
302 .expect("Could not collect the values from the stream");
303 assert_eq!(
304 values,
305 [
306 "1950-06-15 08:30:00",
307 "1980-01-01 00:00:00",
308 "1987-10-05 14:09:00",
309 "1999-12-31 23:59:00",
310 "2025-01-01 00:00:00",
311 ]
312 );
313
314 let mut query_time_1 = executor
316 .prepare(
317 QueryBuilder::new()
318 .select([Times::time_1])
319 .from(Times::table())
320 .where_expr(true)
321 .order_by(cols!(Times::time_1 DESC))
322 .build(&executor.driver()),
323 )
324 .await
325 .expect("Could not prepare the query timestamp 1");
326 let values = executor
327 .fetch(&mut query_time_1)
328 .and_then(|v| async {
329 NaiveTime::try_from_value(
330 v.values
331 .into_iter()
332 .next()
333 .expect("Could not get the first column"),
334 )
335 .map(|v| v.to_string())
336 })
337 .try_collect::<Vec<_>>()
338 .await
339 .expect("Could not collect the values from the stream");
340 assert_eq!(
341 values,
342 [
343 "23:59:00", "18:45:59", "14:09:00", "09:42:00", "08:30:00", "03:14:07", "00:00:00",
344 "00:00:00", "00:00:00",
345 ]
346 );
347
348 let before = SystemTime::now()
350 .duration_since(UNIX_EPOCH)
351 .unwrap()
352 .as_millis()
353 - 2;
354 let timestamp_ms = executor
355 .fetch(
356 QueryBuilder::new()
357 .select([&Operand::CurrentTimestampMs])
358 .from(Times::table())
359 .where_expr(true)
360 .limit(Some(1))
361 .build(&executor.driver()),
362 )
363 .map_ok(|v| u128::try_from_value(v.values.into_iter().nth(0).expect("There is no column")))
364 .map(Result::flatten)
365 .try_collect::<Vec<_>>()
366 .await
367 .expect("Could not get the current timestamp");
368 let after = SystemTime::now()
369 .duration_since(UNIX_EPOCH)
370 .unwrap()
371 .as_millis()
372 + 2;
373 let timestamp_ms = timestamp_ms.into_iter().next().unwrap();
374 assert!(before <= timestamp_ms, "{before} <= {timestamp_ms}");
375 assert!(timestamp_ms <= after, "{timestamp_ms} <= {after}");
376}