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(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 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 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}