1use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
2use std::sync::LazyLock;
3use tank::{AsValue, DataSet, Entity, Executor, cols, expr, stream::TryStreamExt};
4use time::{Date, Month, PrimitiveDateTime, Time};
5use tokio::sync::Mutex;
6
7#[derive(Entity, Debug, Clone, PartialEq, Eq, Hash)]
8pub struct Times {
9 pub timestamp_1: PrimitiveDateTime,
10 pub timestamp_2: chrono::NaiveDateTime,
11 pub date_1: Date,
12 pub date_2: NaiveDate,
13 pub time_1: time::Time,
14 pub time_2: NaiveTime,
15}
16static MUTEX: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
17
18pub async fn times<E: Executor>(executor: &mut E) {
19 let _lock = MUTEX.lock().await;
20
21 Times::drop_table(executor, true, false)
23 .await
24 .expect("Failed to drop Times table");
25 Times::create_table(executor, false, true)
26 .await
27 .expect("Failed to create Times table");
28
29 let timestamps = [
31 Times {
33 timestamp_1: PrimitiveDateTime::new(
34 Date::from_calendar_date(1980, Month::January, 1).unwrap(),
35 Time::from_hms(0, 0, 0).unwrap(),
36 ),
37 timestamp_2: NaiveDateTime::new(
38 NaiveDate::from_ymd_opt(1980, 1, 1).unwrap(),
39 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
40 ),
41 date_1: Date::from_calendar_date(1980, Month::January, 1).unwrap(),
42 date_2: NaiveDate::from_ymd_opt(1980, 1, 1).unwrap(),
43 time_1: Time::from_hms(0, 0, 0).unwrap(),
44 time_2: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
45 },
46 Times {
48 timestamp_1: PrimitiveDateTime::new(
49 Date::from_calendar_date(1987, Month::October, 5).unwrap(),
50 Time::from_hms(14, 9, 0).unwrap(),
51 ),
52 timestamp_2: NaiveDateTime::new(
53 NaiveDate::from_ymd_opt(1987, 10, 5).unwrap(),
54 NaiveTime::from_hms_opt(14, 9, 0).unwrap(),
55 ),
56 date_1: Date::from_calendar_date(1987, Month::October, 5).unwrap(),
57 date_2: NaiveDate::from_ymd_opt(1987, 10, 5).unwrap(),
58 time_1: Time::from_hms(14, 9, 0).unwrap(),
59 time_2: NaiveTime::from_hms_opt(14, 9, 0).unwrap(),
60 },
61 Times {
63 timestamp_1: PrimitiveDateTime::new(
64 Date::from_calendar_date(1999, Month::December, 31).unwrap(),
65 Time::from_hms(23, 59, 0).unwrap(),
66 ),
67 timestamp_2: NaiveDateTime::new(
68 NaiveDate::from_ymd_opt(1999, 12, 31).unwrap(),
69 NaiveTime::from_hms_opt(23, 59, 0).unwrap(),
70 ),
71 date_1: Date::from_calendar_date(1999, Month::December, 31).unwrap(),
72 date_2: NaiveDate::from_ymd_opt(1999, 12, 31).unwrap(),
73 time_1: Time::from_hms(23, 59, 0).unwrap(),
74 time_2: NaiveTime::from_hms_opt(23, 59, 0).unwrap(),
75 },
76 Times {
78 timestamp_1: PrimitiveDateTime::new(
79 Date::from_calendar_date(2025, Month::January, 1).unwrap(),
80 Time::from_hms(0, 0, 0).unwrap(),
81 ),
82 timestamp_2: NaiveDateTime::new(
83 NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
84 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
85 ),
86 date_1: Date::from_calendar_date(2025, Month::January, 1).unwrap(),
87 date_2: NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
88 time_1: Time::from_hms(0, 0, 0).unwrap(),
89 time_2: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
90 },
91 Times {
93 timestamp_1: PrimitiveDateTime::new(
94 Date::from_calendar_date(1950, Month::June, 15).unwrap(),
95 Time::from_hms(8, 30, 0).unwrap(),
96 ),
97 timestamp_2: NaiveDateTime::new(
98 NaiveDate::from_ymd_opt(1950, 6, 15).unwrap(),
99 NaiveTime::from_hms_opt(8, 30, 0).unwrap(),
100 ),
101 date_1: Date::from_calendar_date(1950, Month::June, 15).unwrap(),
102 date_2: NaiveDate::from_ymd_opt(1950, 6, 15).unwrap(),
103 time_1: Time::from_hms(8, 30, 0).unwrap(),
104 time_2: NaiveTime::from_hms_opt(8, 30, 0).unwrap(),
105 },
106 Times {
108 timestamp_1: PrimitiveDateTime::new(
109 Date::from_calendar_date(2038, Month::January, 19).unwrap(),
110 Time::from_hms(3, 14, 7).unwrap(),
111 ),
112 timestamp_2: NaiveDateTime::new(
113 NaiveDate::from_ymd_opt(2038, 1, 19).unwrap(),
114 NaiveTime::from_hms_opt(3, 14, 7).unwrap(),
115 ),
116 date_1: Date::from_calendar_date(2038, Month::January, 19).unwrap(),
117 date_2: NaiveDate::from_ymd_opt(2038, 1, 19).unwrap(),
118 time_1: Time::from_hms(3, 14, 7).unwrap(),
119 time_2: NaiveTime::from_hms_opt(3, 14, 7).unwrap(),
120 },
121 Times {
123 timestamp_1: PrimitiveDateTime::new(
124 Date::from_calendar_date(2025, Month::July, 19).unwrap(),
125 Time::from_hms(9, 42, 0).unwrap(),
126 ),
127 timestamp_2: NaiveDateTime::new(
128 NaiveDate::from_ymd_opt(2025, 7, 19).unwrap(),
129 NaiveTime::from_hms_opt(9, 42, 0).unwrap(),
130 ),
131 date_1: Date::from_calendar_date(2025, Month::July, 19).unwrap(),
132 date_2: NaiveDate::from_ymd_opt(2025, 7, 19).unwrap(),
133 time_1: Time::from_hms(9, 42, 0).unwrap(),
134 time_2: NaiveTime::from_hms_opt(9, 42, 0).unwrap(),
135 },
136 Times {
138 timestamp_1: PrimitiveDateTime::new(
139 Date::from_calendar_date(2050, Month::November, 11).unwrap(),
140 Time::from_hms(18, 45, 59).unwrap(),
141 ),
142 timestamp_2: NaiveDateTime::new(
143 NaiveDate::from_ymd_opt(2050, 11, 11).unwrap(),
144 NaiveTime::from_hms_opt(18, 45, 59).unwrap(),
145 ),
146 date_1: Date::from_calendar_date(2050, Month::November, 11).unwrap(),
147 date_2: NaiveDate::from_ymd_opt(2050, 11, 11).unwrap(),
148 time_1: Time::from_hms(18, 45, 59).unwrap(),
149 time_2: NaiveTime::from_hms_opt(18, 45, 59).unwrap(),
150 },
151 Times {
153 timestamp_1: PrimitiveDateTime::new(
154 Date::from_calendar_date(2050, Month::September, 9).unwrap(),
155 Time::from_hms(0, 0, 0).unwrap(),
156 ),
157 timestamp_2: NaiveDateTime::new(
158 NaiveDate::from_ymd_opt(2050, 9, 9).unwrap(),
159 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
160 ),
161 date_1: Date::from_calendar_date(2050, Month::September, 9).unwrap(),
162 date_2: NaiveDate::from_ymd_opt(2050, 9, 9).unwrap(),
163 time_1: Time::from_hms(0, 0, 0).unwrap(),
164 time_2: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
165 },
166 ];
167
168 Times::insert_many(executor, ×tamps)
169 .await
170 .expect("Failed to insert timestamps");
171
172 let mut query_timestamp_1 = Times::table()
186 .prepare(
187 executor,
188 cols!(Times::timestamp_1 DESC),
189 &expr!(Times::timestamp_2 > ?),
190 None,
191 )
192 .await
193 .expect("Could not prepare the query timestamp 1");
194 query_timestamp_1
195 .bind(PrimitiveDateTime::new(
196 Date::from_calendar_date(1999, Month::December, 31).unwrap(),
197 Time::from_hms(23, 59, 59).unwrap(),
198 ))
199 .expect("Could not bind the timestamp 1");
200 let values = executor
201 .fetch(&mut query_timestamp_1)
202 .and_then(|v| async {
203 PrimitiveDateTime::try_from_value(
204 v.values
205 .into_iter()
206 .next()
207 .expect("Could not get the first column"),
208 )
209 .map(|v| v.to_string())
210 })
211 .try_collect::<Vec<_>>()
212 .await
213 .expect("Could not collect the values from the stream");
214 assert_eq!(
215 values,
216 [
217 "2050-11-11 18:45:59.0",
218 "2050-09-09 0:00:00.0",
219 "2038-01-19 3:14:07.0",
220 "2025-07-19 9:42:00.0",
221 "2025-01-01 0:00:00.0",
222 ]
223 );
224 query_timestamp_1
225 .clear_bindings()
226 .expect("Could not clear the bindings for query timestamp 1");
227 query_timestamp_1
228 .bind(PrimitiveDateTime::new(
229 Date::from_calendar_date(1800, Month::January, 1).unwrap(),
230 Time::from_hms(0, 0, 0).unwrap(),
231 ))
232 .expect("Could not bind the timestamp 1");
233 let values = executor
234 .fetch(&mut query_timestamp_1)
235 .and_then(|v| async {
236 NaiveDateTime::try_from_value(
237 v.values
238 .into_iter()
239 .next()
240 .expect("Could not get the first column"),
241 )
242 .map(|v| v.to_string())
243 })
244 .try_collect::<Vec<_>>()
245 .await
246 .expect("Could not collect the values from the stream");
247 assert_eq!(
248 values,
249 [
250 "2050-11-11 18:45:59",
251 "2050-09-09 00:00:00",
252 "2038-01-19 03:14:07",
253 "2025-07-19 09:42:00",
254 "2025-01-01 00:00:00",
255 "1999-12-31 23:59:00",
256 "1987-10-05 14:09:00",
257 "1980-01-01 00:00:00",
258 "1950-06-15 08:30:00",
259 ]
260 );
261
262 let mut query_timestamp_2 = Times::table()
264 .prepare(
265 executor,
266 cols!(Times::timestamp_2 ASC),
267 &expr!(Times::timestamp_1 <= ?),
268 None,
269 )
270 .await
271 .expect("Could not prepare the query timestamp 1");
272 query_timestamp_2
273 .bind(NaiveDateTime::new(
274 NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
275 NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
276 ))
277 .expect("Could not bind the timestamp 1");
278 let values = executor
279 .fetch(&mut query_timestamp_2)
280 .and_then(|v| async {
281 NaiveDateTime::try_from_value(
282 v.values
283 .into_iter()
284 .next()
285 .expect("Could not get the first column"),
286 )
287 .map(|v| v.to_string())
288 })
289 .try_collect::<Vec<_>>()
290 .await
291 .expect("Could not collect the values from the stream");
292 assert_eq!(
293 values,
294 [
295 "1950-06-15 08:30:00",
296 "1980-01-01 00:00:00",
297 "1987-10-05 14:09:00",
298 "1999-12-31 23:59:00",
299 "2025-01-01 00:00:00",
300 ]
301 );
302
303 let mut query_time_1 = Times::table()
305 .prepare(executor, cols!(Times::time_1 DESC), &true, None)
306 .await
307 .expect("Could not prepare the query timestamp 1");
308 let values = executor
309 .fetch(&mut query_time_1)
310 .and_then(|v| async {
311 NaiveTime::try_from_value(
312 v.values
313 .into_iter()
314 .next()
315 .expect("Could not get the first column"),
316 )
317 .map(|v| v.to_string())
318 })
319 .try_collect::<Vec<_>>()
320 .await
321 .expect("Could not collect the values from the stream");
322 assert_eq!(
323 values,
324 [
325 "23:59:00", "18:45:59", "14:09:00", "09:42:00", "08:30:00", "03:14:07", "00:00:00",
326 "00:00:00", "00:00:00",
327 ]
328 );
329}