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 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 let timestamps = [
32 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 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 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 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 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 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 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 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 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, ×tamps)
170 .await
171 .expect("Failed to insert timestamps");
172
173 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 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 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}