1use rhai::def_package;
2use rhai::plugin::*;
3
4pub(crate) mod datetime;
5pub(crate) mod timedelta;
6
7def_package! {
8 pub ChronoPackage(lib) {
10 combine_with_exported_module!(lib, "rhai_chrono_datetime", datetime::datetime_module);
11 combine_with_exported_module!(lib, "rhai_chrono_timedelta", timedelta::timedelta_module);
12 }
13}
14
15#[cfg(test)]
16mod tests {
17 use chrono::{DateTime, Datelike, Days, Local, Months, NaiveTime, TimeDelta, Timelike, Utc};
18
19 use chrono_tz::Tz;
20 use rhai::packages::Package;
21 use rhai::Engine;
22
23 use crate::datetime::datetime_module::DateTimeFixed;
24 use crate::timedelta::timedelta_module::Timedelta;
25 use crate::ChronoPackage;
26
27 fn get_engine() -> Engine {
28 let mut engine = Engine::new();
29
30 let package = ChronoPackage::new();
31 package.register_into_engine(&mut engine);
32
33 engine
34 }
35
36 #[test]
37 fn it_works() {
38 let engine = get_engine();
39
40 let timestamp_unix: u64 = 618658211;
41 let timestamp_unix_millis: u64 = 618658211123;
42 let timestamp_unix_micros: u64 = 618658211123456;
43 let timestamp_unix_nanos: u64 = 618658211123456789;
44 let timestamp_unix_alt = 487772700;
45 let timestamp_mysql = "1989-08-09 09:30:11";
46 let timestamp_mysql_format = "%Y-%m-%d %H:%M:%S";
47 let timestamp_rfc2822 = "Wed, 9 Aug 1989 09:30:11 +0000";
48 let timestamp_rfc3339 = "1989-08-09T09:30:11+00:00";
49 let timestamp_rfc3339_millis = "1989-08-09T09:30:11.123+00:00";
50 let timestamp_rfc3339_micros = "1989-08-09T09:30:11.123456+00:00";
51 let timestamp_rfc3339_nanos = "1989-08-09T09:30:11.123456789+00:00";
52 let timestamp_localized = "mercredi, août 9";
53 let timestamp_localized_format = "%A, %B %e";
54 let timestamp_localized_locale = "fr_FR";
55
56 assert!(
58 engine.eval::<DateTimeFixed>(r#"datetime_now()"#).is_ok(),
59 "we should be getting Utc::now()"
60 );
61
62 assert!(
64 engine.eval::<DateTimeFixed>(r#"datetime_utc()"#).is_ok(),
65 "we should be getting Utc::now()"
66 );
67
68 assert!(
70 engine.eval::<DateTimeFixed>(r#"datetime_local()"#).is_ok(),
71 "we should be getting Local::now()"
72 );
73
74 assert!(
76 engine.eval::<String>(r#"let dt = datetime_utc(); dt.to_string()"#).is_ok(),
77 "we should be getting RFC3339 string"
78 );
79
80 assert!(
82 engine.eval::<String>(r#"let dt = datetime_local(); dt.to_string()"#).is_ok(),
83 "we should be getting RFC3339 string"
84 );
85
86 assert_eq!(
88 engine
89 .eval::<String>(&format!(r#"let dt = datetime_unix({}); dt.to_string()"#, timestamp_unix))
90 .unwrap_or_default(),
91 timestamp_rfc3339,
92 "we should be getting RFC3339 string"
93 );
94
95 assert_eq!(
97 engine
98 .eval::<String>(&format!(r#"let dt = datetime_millis({}); dt.to_string()"#, timestamp_unix_millis))
99 .unwrap_or_default(),
100 timestamp_rfc3339_millis,
101 "we should be getting RFC3339 string"
102 );
103
104 assert_eq!(
106 engine
107 .eval::<String>(&format!(r#"let dt = datetime_micros({}); dt.to_string()"#, timestamp_unix_micros))
108 .unwrap_or_default(),
109 timestamp_rfc3339_micros,
110 "we should be getting RFC3339 string"
111 );
112
113 assert_eq!(
115 engine
116 .eval::<String>(&format!(r#"let dt = datetime_nanos({}); dt.to_string()"#, timestamp_unix_nanos))
117 .unwrap_or_default(),
118 timestamp_rfc3339_nanos,
119 "we should be getting RFC3339 string"
120 );
121
122 assert_eq!(
124 engine
125 .eval::<String>(&format!(r#"let dt = datetime_rfc2822("{}"); dt.to_string()"#, timestamp_rfc2822))
126 .unwrap_or_default(),
127 timestamp_rfc3339,
128 "we should be getting RFC3339 string"
129 );
130
131 assert_eq!(
133 engine
134 .eval::<String>(&format!(r#"let dt = datetime_rfc3339("{}"); dt.to_string()"#, timestamp_rfc3339))
135 .unwrap_or_default(),
136 timestamp_rfc3339,
137 "we should be getting RFC3339 string"
138 );
139
140 assert_eq!(
142 engine
143 .eval::<String>(&format!(
144 r#"let dt = datetime_parse("{}", "{}"); dt.to_string()"#,
145 timestamp_mysql, timestamp_mysql_format
146 ))
147 .unwrap_or_default(),
148 timestamp_rfc3339,
149 "we should be getting RFC3339 string"
150 );
151
152 assert!(
154 engine.eval::<String>(r#"let dt = datetime_utc(); dt.to_rfc3339()"#).is_ok(),
155 "we should be getting RFC3339 string"
156 );
157
158 assert!(
160 engine.eval::<String>(r#"let dt = datetime_local(); dt.to_rfc3339()"#).is_ok(),
161 "we should be getting RFC3339 string"
162 );
163
164 assert_eq!(
166 engine
167 .eval::<String>(&format!(r#"let dt = datetime_rfc3339("{}"); dt.to_rfc2822()"#, timestamp_rfc3339))
168 .unwrap_or_default(),
169 timestamp_rfc2822,
170 "we should be getting RFC2822 string"
171 );
172
173 assert_eq!(
175 engine
176 .eval::<i64>(&format!(r#"let dt = datetime_rfc2822("{}"); dt.timestamp()"#, timestamp_rfc2822))
177 .unwrap_or_default(),
178 timestamp_unix as i64,
179 "we should be getting UNIX timestamp i64"
180 );
181
182 assert_eq!(
184 engine
185 .eval::<i64>(&format!(
186 r#"let dt = datetime_rfc3339("{}"); dt.timestamp_millis()"#,
187 timestamp_rfc3339_millis
188 ))
189 .unwrap_or_default(),
190 timestamp_unix_millis as i64,
191 "we should be getting UNIX milliseconds timestamp i64"
192 );
193
194 assert_eq!(
196 engine
197 .eval::<i64>(&format!(
198 r#"let dt = datetime_rfc3339("{}"); dt.timestamp_micros()"#,
199 timestamp_rfc3339_micros
200 ))
201 .unwrap_or_default(),
202 timestamp_unix_micros as i64,
203 "we should be getting UNIX microseconds timestamp i64"
204 );
205
206 assert_eq!(
208 engine
209 .eval::<i64>(&format!(
210 r#"let dt = datetime_rfc3339("{}"); dt.timestamp_nanos()"#,
211 timestamp_rfc3339_nanos
212 ))
213 .unwrap_or_default(),
214 timestamp_unix_nanos as i64,
215 "we should be getting UNIX nanoseconds timestamp i64"
216 );
217
218 assert_eq!(
220 engine
221 .eval::<rhai::INT>(&format!(
222 r#"let dt = datetime_rfc3339("{}"); dt.timestamp_subsec_millis()"#,
223 timestamp_rfc3339_nanos
224 ))
225 .unwrap_or_default(),
226 123u32 as rhai::INT,
227 "we should be getting UNIX milliseconds remainder"
228 );
229
230 assert_eq!(
232 engine
233 .eval::<rhai::INT>(&format!(
234 r#"let dt = datetime_rfc3339("{}"); dt.timestamp_subsec_micros()"#,
235 timestamp_rfc3339_nanos
236 ))
237 .unwrap_or_default(),
238 123456u32 as rhai::INT,
239 "we should be getting UNIX microseconds remainder"
240 );
241
242 assert_eq!(
244 engine
245 .eval::<rhai::INT>(&format!(
246 r#"let dt = datetime_rfc3339("{}"); dt.timestamp_subsec_nanos()"#,
247 timestamp_rfc3339_nanos
248 ))
249 .unwrap_or_default(),
250 123456789u32 as rhai::INT,
251 "we should be getting UNIX nanoseconds remainder"
252 );
253
254 let years_since = Local::now()
256 .fixed_offset()
257 .years_since(DateTime::from_timestamp_nanos(timestamp_unix_nanos as i64).fixed_offset())
258 .unwrap_or_default() as i32;
259
260 assert_eq!(
261 engine
262 .eval::<rhai::INT>(&format!(
263 r#"let dt = datetime_now(); dt.years_since(datetime_rfc3339("{}"))"#,
264 timestamp_rfc3339_nanos
265 ))
266 .unwrap_or_default(),
267 years_since as rhai::INT,
268 "we should be getting number of years"
269 );
270
271 assert_eq!(
272 engine
273 .eval::<rhai::INT>(&format!(
274 r#"let dt = datetime_rfc3339("{}"); dt.years_since()"#,
275 timestamp_rfc3339_nanos
276 ))
277 .unwrap_or_default(),
278 (years_since * -1i32) as rhai::INT,
279 "we should be getting number of years"
280 );
281
282 assert_eq!(
283 engine
284 .eval::<rhai::INT>(&format!(
285 r#"let dt = datetime_parse("2111-03-05 11:25:00", "{}"); dt.years_since()"#,
286 timestamp_mysql_format
287 ))
288 .unwrap_or_default()
289 > 10,
290 true,
291 "we should be getting number of years"
292 );
293
294 assert_eq!(
295 engine
296 .eval::<rhai::INT>(&format!(
297 r#"let dt = datetime_rfc3339("{}"); dt.years_since(datetime_now())"#,
298 timestamp_rfc3339_nanos
299 ))
300 .unwrap_or_default(),
301 (years_since * -1i32) as rhai::INT,
302 "we should be getting number of years"
303 );
304
305 assert_eq!(
307 engine
308 .eval::<String>(&format!(
309 r#"let dt = datetime_rfc2822("{}"); dt.format("{}")"#,
310 timestamp_rfc2822, timestamp_mysql_format
311 ))
312 .unwrap_or_default(),
313 timestamp_mysql,
314 "we should be getting MySQL datetime string"
315 );
316
317 assert_eq!(
319 engine
320 .eval::<String>(&format!(
321 r#"let dt = datetime_rfc2822("{}"); dt.format("{}", "{}")"#,
322 timestamp_rfc2822, timestamp_localized_format, timestamp_localized_locale
323 ))
324 .unwrap_or_default(),
325 timestamp_localized,
326 "we should be getting pretty french words"
327 );
328
329 assert_eq!(
331 engine
332 .eval::<String>(&format!(
333 r#"let dt = datetime_rfc3339("{}"); dt.timezone("local"); dt.to_rfc2822()"#,
334 timestamp_rfc3339
335 ))
336 .unwrap_or_default(),
337 DateTime::parse_from_rfc2822(timestamp_rfc2822)
338 .unwrap()
339 .with_timezone(&Local::now().fixed_offset().timezone())
340 .to_rfc2822(),
341 "we should be getting RFC2822 string"
342 );
343
344 assert_eq!(
346 engine
347 .eval::<String>(&format!(
348 r#"let dt = datetime_rfc3339("{}"); dt.timezone("local"); dt.timezone"#,
349 timestamp_rfc3339
350 ))
351 .unwrap_or_default(),
352 Local::now().fixed_offset().timezone().to_string(),
353 "we should be getting offset string"
354 );
355
356 assert_eq!(
358 engine
359 .eval::<String>(&format!(
360 r#"let dt = datetime_rfc3339("{}"); dt.timezone("America/Edmonton"); dt.to_rfc2822()"#,
361 timestamp_rfc3339
362 ))
363 .unwrap_or_default(),
364 DateTime::parse_from_rfc2822(timestamp_rfc2822)
365 .unwrap()
366 .with_timezone(&chrono_tz::America::Edmonton)
367 .to_rfc2822(),
368 "we should be getting RFC2822 string"
369 );
370
371 assert_eq!(
373 engine
374 .eval::<String>(&format!(
375 r#"let dt = datetime_rfc3339("{}"); dt.timezone("America/Edmonton"); dt.timezone"#,
376 timestamp_rfc3339
377 ))
378 .unwrap_or_default(),
379 Utc::now().with_timezone(&Tz::America__Edmonton).fixed_offset().offset().to_string(),
380 "we should be getting offset string"
381 );
382
383 assert_eq!(
385 engine
386 .eval::<String>(&format!(
387 r#"let dt = datetime_rfc3339("{}"); dt.timezone("-06:00"); dt.to_rfc2822()"#,
388 timestamp_rfc3339
389 ))
390 .unwrap_or_default(),
391 DateTime::parse_from_rfc2822(timestamp_rfc2822)
392 .unwrap()
393 .with_timezone(&chrono_tz::America::Edmonton)
394 .to_rfc2822(),
395 "we should be getting RFC2822 string"
396 );
397
398 assert_eq!(
400 engine
401 .eval::<String>(&format!(
402 r#"let dt = datetime_rfc3339("{}"); dt.timezone("-06:00"); dt.timezone"#,
403 timestamp_rfc3339
404 ))
405 .unwrap_or_default(),
406 "-06:00".to_string(),
407 "we should be getting offset string"
408 );
409
410 assert_eq!(
412 engine
413 .eval::<String>(&format!(
414 r#"let dt = datetime_rfc3339("{}"); dt.timezone("-06:00"); dt.offset"#,
415 timestamp_rfc3339
416 ))
417 .unwrap_or_default(),
418 "-06:00".to_string(),
419 "we should be getting offset string"
420 );
421
422 assert_eq!(
424 engine
425 .eval::<String>(&format!(
426 r#"let dt = datetime_rfc3339("{}"); dt.time("12:15"); dt.to_rfc2822()"#,
427 timestamp_rfc3339
428 ))
429 .unwrap_or_default(),
430 DateTime::parse_from_rfc2822(timestamp_rfc2822)
431 .unwrap()
432 .with_time(NaiveTime::from_hms_opt(12, 15, 0).unwrap())
433 .unwrap()
434 .to_rfc2822(),
435 "we should be getting RFC2822 string"
436 );
437
438 assert_eq!(
440 engine
441 .eval::<String>(&format!(
442 r#"let dt = datetime_rfc3339("{}"); dt.time("12:15"); dt.time"#,
443 timestamp_rfc3339
444 ))
445 .unwrap_or_default(),
446 "12:15:00".to_string(),
447 "we should be getting RFC2822 string"
448 );
449
450 assert_eq!(
452 engine
453 .eval::<String>(&format!(
454 r#"let dt = datetime_rfc3339("{}"); dt.ordinal(5); dt.to_rfc2822()"#,
455 timestamp_rfc3339
456 ))
457 .unwrap_or_default(),
458 DateTime::parse_from_rfc2822(timestamp_rfc2822)
459 .unwrap()
460 .with_ordinal(5)
461 .unwrap()
462 .to_rfc2822(),
463 "we should be getting RFC2822 string"
464 );
465
466 assert_eq!(
468 engine
469 .eval::<rhai::INT>(&format!(r#"let dt = datetime_rfc3339("{}"); dt.ordinal"#, timestamp_rfc3339))
470 .unwrap_or_default(),
471 221 as rhai::INT,
472 "we should be getting 5"
473 );
474
475 assert_eq!(
477 engine
478 .eval::<String>(&format!(
479 r#"let dt = datetime_rfc3339("{}"); dt.ordinal0(5); dt.to_rfc2822()"#,
480 timestamp_rfc3339
481 ))
482 .unwrap_or_default(),
483 DateTime::parse_from_rfc2822(timestamp_rfc2822)
484 .unwrap()
485 .with_ordinal0(5)
486 .unwrap()
487 .to_rfc2822(),
488 "we should be getting RFC2822 string"
489 );
490
491 assert_eq!(
493 engine
494 .eval::<rhai::INT>(&format!(
495 r#"let dt = datetime_rfc3339("{}"); dt.ordinal0(5); dt.ordinal0"#,
496 timestamp_rfc3339
497 ))
498 .unwrap_or_default(),
499 5 as rhai::INT,
500 "we should be getting 5"
501 );
502
503 assert_eq!(
505 engine
506 .eval::<String>(&format!(
507 r#"let dt = datetime_rfc3339("{}"); dt.year(1990); dt.to_rfc2822()"#,
508 timestamp_rfc3339
509 ))
510 .unwrap_or_default(),
511 DateTime::parse_from_rfc2822(timestamp_rfc2822)
512 .unwrap()
513 .with_year(1990)
514 .unwrap()
515 .to_rfc2822(),
516 "we should be getting RFC2822 string"
517 );
518
519 assert_eq!(
521 engine
522 .eval::<rhai::INT>(&format!(r#"let dt = datetime_rfc3339("{}"); dt.year"#, timestamp_rfc3339))
523 .unwrap_or_default(),
524 1989 as rhai::INT,
525 "we should be getting 1989"
526 );
527
528 assert_eq!(
530 engine
531 .eval::<String>(&format!(
532 r#"let dt = datetime_rfc3339("{}"); dt.month(11); dt.to_rfc2822()"#,
533 timestamp_rfc3339
534 ))
535 .unwrap_or_default(),
536 DateTime::parse_from_rfc2822(timestamp_rfc2822)
537 .unwrap()
538 .with_month(11)
539 .unwrap()
540 .to_rfc2822(),
541 "we should be getting RFC2822 string"
542 );
543
544 assert_eq!(
546 engine
547 .eval::<rhai::INT>(&format!(r#"let dt = datetime_rfc3339("{}"); dt.month"#, timestamp_rfc3339))
548 .unwrap_or_default(),
549 8 as rhai::INT,
550 "we should be getting 8"
551 );
552
553 assert_eq!(
555 engine
556 .eval::<String>(&format!(
557 r#"let dt = datetime_rfc3339("{}"); dt.month0(10); dt.to_rfc2822()"#,
558 timestamp_rfc3339
559 ))
560 .unwrap_or_default(),
561 DateTime::parse_from_rfc2822(timestamp_rfc2822)
562 .unwrap()
563 .with_month0(10)
564 .unwrap()
565 .to_rfc2822(),
566 "we should be getting RFC2822 string"
567 );
568
569 assert_eq!(
571 engine
572 .eval::<rhai::INT>(&format!(
573 r#"let dt = datetime_rfc3339("{}"); dt.month0(10); dt.month0"#,
574 timestamp_rfc3339
575 ))
576 .unwrap_or_default(),
577 10 as rhai::INT,
578 "we should be getting RFC2822 string"
579 );
580
581 assert_eq!(
583 engine
584 .eval::<String>(&format!(
585 r#"let dt = datetime_rfc3339("{}"); dt.day(11); dt.to_rfc2822()"#,
586 timestamp_rfc3339
587 ))
588 .unwrap_or_default(),
589 DateTime::parse_from_rfc2822(timestamp_rfc2822)
590 .unwrap()
591 .with_day(11)
592 .unwrap()
593 .to_rfc2822(),
594 "we should be getting RFC2822 string"
595 );
596
597 assert_eq!(
599 engine
600 .eval::<rhai::INT>(&format!(r#"let dt = datetime_rfc3339("{}"); dt.day"#, timestamp_rfc3339))
601 .unwrap_or_default(),
602 9 as rhai::INT,
603 "we should be getting 9"
604 );
605
606 assert_eq!(
608 engine
609 .eval::<String>(&format!(
610 r#"let dt = datetime_rfc3339("{}"); dt.day0(10); dt.to_rfc2822()"#,
611 timestamp_rfc3339
612 ))
613 .unwrap_or_default(),
614 DateTime::parse_from_rfc2822(timestamp_rfc2822)
615 .unwrap()
616 .with_day0(10)
617 .unwrap()
618 .to_rfc2822(),
619 "we should be getting RFC2822 string"
620 );
621 assert_eq!(
623 engine
624 .eval::<rhai::INT>(&format!(
625 r#"let dt = datetime_rfc3339("{}"); dt.day0(10); dt.day0"#,
626 timestamp_rfc3339
627 ))
628 .unwrap_or_default(),
629 10 as rhai::INT,
630 "we should be getting RFC2822 string"
631 );
632
633 assert_eq!(
635 engine
636 .eval::<String>(&format!(
637 r#"let dt = datetime_rfc3339("{}"); dt.hour(23); dt.to_rfc2822()"#,
638 timestamp_rfc3339
639 ))
640 .unwrap_or_default(),
641 DateTime::parse_from_rfc2822(timestamp_rfc2822)
642 .unwrap()
643 .with_hour(23)
644 .unwrap()
645 .to_rfc2822(),
646 "we should be getting RFC2822 string"
647 );
648
649 assert_eq!(
651 engine
652 .eval::<rhai::INT>(&format!(r#"let dt = datetime_rfc3339("{}"); dt.hour"#, timestamp_rfc3339))
653 .unwrap_or_default(),
654 9 as rhai::INT,
655 "we should be getting 9"
656 );
657
658 assert_eq!(
660 engine
661 .eval::<String>(&format!(
662 r#"let dt = datetime_rfc3339("{}"); dt.minute(33); dt.to_rfc2822()"#,
663 timestamp_rfc3339
664 ))
665 .unwrap_or_default(),
666 DateTime::parse_from_rfc2822(timestamp_rfc2822)
667 .unwrap()
668 .with_minute(33)
669 .unwrap()
670 .to_rfc2822(),
671 "we should be getting RFC2822 string"
672 );
673
674 assert_eq!(
675 engine
676 .eval::<rhai::INT>(&format!(r#"let dt = datetime_rfc3339("{}"); dt.minute"#, timestamp_rfc3339))
677 .unwrap_or_default(),
678 30 as rhai::INT,
679 "we should be getting 30"
680 );
681
682 assert_eq!(
684 engine
685 .eval::<String>(&format!(
686 r#"let dt = datetime_rfc3339("{}"); dt.second(7); dt.to_rfc2822()"#,
687 timestamp_rfc3339
688 ))
689 .unwrap_or_default(),
690 DateTime::parse_from_rfc2822(timestamp_rfc2822)
691 .unwrap()
692 .with_second(7)
693 .unwrap()
694 .to_rfc2822(),
695 "we should be getting RFC2822 string"
696 );
697
698 assert_eq!(
699 engine
700 .eval::<rhai::INT>(&format!(
701 r#"let dt = datetime_rfc3339("{}"); dt.second(7); dt.second"#,
702 timestamp_rfc3339
703 ))
704 .unwrap_or_default(),
705 7 as rhai::INT,
706 "we should be getting 7"
707 );
708
709 assert_eq!(
711 engine
712 .eval::<String>(&format!(
713 r#"let dt = datetime_rfc3339("{}"); dt.nanosecond(123456789); dt.to_rfc2822()"#,
714 timestamp_rfc3339
715 ))
716 .unwrap_or_default(),
717 DateTime::parse_from_rfc2822(timestamp_rfc2822)
718 .unwrap()
719 .with_nanosecond(123456789)
720 .unwrap()
721 .to_rfc2822(),
722 "we should be getting RFC2822 string"
723 );
724
725 assert_eq!(
726 engine
727 .eval::<rhai::INT>(&format!(
728 r#"let dt = datetime_rfc3339("{}"); dt.nanosecond(123456789); dt.nanosecond"#,
729 timestamp_rfc3339
730 ))
731 .unwrap_or_default(),
732 123456789 as rhai::INT,
733 "we should be getting RFC2822 string"
734 );
735
736 assert_eq!(
738 engine
739 .eval::<String>(&format!(
740 r#"let dt = datetime_rfc3339("{}"); dt.add_days(3); dt.to_rfc2822()"#,
741 timestamp_rfc3339
742 ))
743 .unwrap_or_default(),
744 DateTime::parse_from_rfc2822(timestamp_rfc2822)
745 .unwrap()
746 .checked_add_days(Days::new(3))
747 .unwrap()
748 .to_rfc2822(),
749 "we should be getting RFC2822 string"
750 );
751
752 assert_eq!(
754 engine
755 .eval::<String>(&format!(
756 r#"let dt = datetime_rfc3339("{}"); dt.sub_days(3); dt.to_rfc2822()"#,
757 timestamp_rfc3339
758 ))
759 .unwrap_or_default(),
760 DateTime::parse_from_rfc2822(timestamp_rfc2822)
761 .unwrap()
762 .checked_sub_days(Days::new(3))
763 .unwrap()
764 .to_rfc2822(),
765 "we should be getting RFC2822 string"
766 );
767
768 assert_eq!(
770 engine
771 .eval::<String>(&format!(
772 r#"let dt = datetime_rfc3339("{}"); dt.add_months(2); dt.to_rfc2822()"#,
773 timestamp_rfc3339
774 ))
775 .unwrap_or_default(),
776 DateTime::parse_from_rfc2822(timestamp_rfc2822)
777 .unwrap()
778 .checked_add_months(Months::new(2))
779 .unwrap()
780 .to_rfc2822(),
781 "we should be getting RFC2822 string"
782 );
783
784 assert_eq!(
786 engine
787 .eval::<String>(&format!(
788 r#"let dt = datetime_rfc3339("{}"); dt.sub_months(2); dt.to_rfc2822()"#,
789 timestamp_rfc3339
790 ))
791 .unwrap_or_default(),
792 DateTime::parse_from_rfc2822(timestamp_rfc2822)
793 .unwrap()
794 .checked_sub_months(Months::new(2))
795 .unwrap()
796 .to_rfc2822(),
797 "we should be getting RFC2822 string"
798 );
799
800 assert_eq!(
802 engine
803 .eval::<rhai::INT>(&format!(
804 r#"
805 let dt = datetime_unix({});
806 let dt2 = datetime_unix({});
807
808 let td = dt.diff(dt2);
809
810 td.seconds
811 "#,
812 timestamp_unix, timestamp_unix_alt
813 ))
814 .unwrap_or_default(),
815 (timestamp_unix - timestamp_unix_alt) as i64,
816 "we should be getting number of seconds difference"
817 );
818
819 assert_eq!(
821 engine
822 .eval::<rhai::INT>(&format!(
823 r#"
824 let dt = datetime_unix({});
825 let td = timedelta_days(2);
826
827 dt.add_timedelta(td);
828
829 dt.timestamp()
830 "#,
831 timestamp_unix
832 ))
833 .unwrap_or_default(),
834 (timestamp_unix + TimeDelta::try_days(2).unwrap().num_seconds() as u64) as i64,
835 "we should be getting number of seconds difference"
836 );
837
838 assert_eq!(
840 engine
841 .eval::<rhai::INT>(&format!(
842 r#"
843 let dt = datetime_unix({});
844 let td = timedelta_days(2);
845
846 dt.sub_timedelta(td);
847
848 dt.timestamp()
849 "#,
850 timestamp_unix
851 ))
852 .unwrap_or_default(),
853 (timestamp_unix - TimeDelta::try_days(2).unwrap().num_seconds() as u64) as i64,
854 "we should be getting number of seconds difference"
855 );
856
857 assert!(
859 engine.eval::<Timedelta>(r#"timedelta_zero()"#).is_ok(),
860 "we should be getting zero timedelta"
861 );
862
863 assert_eq!(
865 engine
866 .eval::<rhai::INT>(r#"let td = timedelta_zero(); td.seconds"#)
867 .unwrap_or_default(),
868 0 as rhai::INT,
869 "we should be getting zero timedelta"
870 );
871
872 assert_eq!(
874 engine
875 .eval::<bool>(r#"let td = timedelta_zero(); td.is_zero()"#)
876 .unwrap_or_default(),
877 true,
878 "we should be getting zero timedelta"
879 );
880
881 assert_eq!(
883 engine.eval::<bool>(r#"let td = timedelta_min(); td.is_zero()"#).unwrap_or_default(),
884 false,
885 "we should be getting min timedelta"
886 );
887
888 assert_eq!(
890 engine.eval::<bool>(r#"let td = timedelta_max(); td.is_zero()"#).unwrap_or_default(),
891 false,
892 "we should be getting max timedelta"
893 );
894
895 assert_eq!(
897 engine
898 .eval::<rhai::INT>(r#"let td = timedelta_seconds(7); td.seconds"#)
899 .unwrap_or_default(),
900 7 as rhai::INT,
901 "we should be getting 7"
902 );
903
904 assert_eq!(
906 engine
907 .eval::<rhai::INT>(r#"let td = timedelta_seconds(7, 123456789); td.seconds"#)
908 .unwrap_or_default(),
909 7 as rhai::INT,
910 "we should be getting 7"
911 );
912
913 assert_eq!(
915 engine
916 .eval::<rhai::INT>(r#"let td = timedelta_seconds(7, 123456789); td.subsec_nanos"#)
917 .unwrap_or_default(),
918 123456789 as rhai::INT,
919 "we should be getting 123456789"
920 );
921
922 assert_eq!(
924 engine
925 .eval::<rhai::INT>(r#"let td = timedelta_days(30); td.seconds"#)
926 .unwrap_or_default(),
927 30 * 86400 as rhai::INT,
928 "we should be getting a month worth of seconds"
929 );
930
931 assert_eq!(
933 engine
934 .eval::<rhai::INT>(r#"let td = timedelta_weeks(4); td.seconds"#)
935 .unwrap_or_default(),
936 28 * 86400 as rhai::INT,
937 "we should be getting 4 weeks worth of seconds"
938 );
939
940 assert_eq!(
942 engine
943 .eval::<rhai::INT>(r#"let td = timedelta_hours(2); td.seconds"#)
944 .unwrap_or_default(),
945 7200 as rhai::INT,
946 "we should be getting 7200"
947 );
948
949 assert_eq!(
951 engine
952 .eval::<rhai::INT>(r#"let td = timedelta_minutes(30); td.seconds"#)
953 .unwrap_or_default(),
954 1800 as rhai::INT,
955 "we should be getting 1800"
956 );
957
958 assert_eq!(
960 engine
961 .eval::<rhai::INT>(r#"let td = timedelta_millis(2000); td.seconds"#)
962 .unwrap_or_default(),
963 2 as rhai::INT,
964 "we should be getting 2"
965 );
966
967 assert_eq!(
969 engine
970 .eval::<rhai::INT>(r#"let td = timedelta_micros(2000000); td.seconds"#)
971 .unwrap_or_default(),
972 2 as rhai::INT,
973 "we should be getting 2"
974 );
975
976 assert_eq!(
978 engine
979 .eval::<rhai::INT>(r#"let td = timedelta_nanos(2000000000); td.seconds"#)
980 .unwrap_or_default(),
981 2 as rhai::INT,
982 "we should be getting 2"
983 );
984
985 assert_eq!(
987 engine
988 .eval::<rhai::INT>(r#"let td = timedelta_weeks(-4); td.abs(); td.seconds"#)
989 .unwrap_or_default(),
990 28 * 86400 as rhai::INT,
991 "we should be getting 4 weeks worth of seconds"
992 );
993
994 assert_eq!(
996 engine
997 .eval::<rhai::INT>(r#"let td = timedelta_weeks(4); let td2 = timedelta_hours(8); td.add(td2); td.seconds"#)
998 .unwrap_or_default(),
999 28 * 86400 + 8 * 3600 as rhai::INT,
1000 "we should be getting 4 weeks and 8h worth of seconds"
1001 );
1002
1003 assert_eq!(
1005 engine
1006 .eval::<rhai::INT>(r#"let td = timedelta_weeks(4); let td2 = timedelta_hours(8); td.sub(td2); td.seconds"#)
1007 .unwrap_or_default(),
1008 28 * 86400 - 8 * 3600 as rhai::INT,
1009 "we should be getting 3 weeks, 6 days and 16h worth of seconds"
1010 );
1011
1012 assert_eq!(
1014 engine
1015 .eval::<rhai::INT>(r#"let td = timedelta_seconds(60); td.minutes"#)
1016 .unwrap_or_default(),
1017 1 as rhai::INT,
1018 "we should be getting 1"
1019 );
1020
1021 assert_eq!(
1023 engine
1024 .eval::<rhai::INT>(r#"let td = timedelta_seconds(3600); td.hours"#)
1025 .unwrap_or_default(),
1026 1 as rhai::INT,
1027 "we should be getting 1"
1028 );
1029
1030 assert_eq!(
1032 engine
1033 .eval::<rhai::INT>(r#"let td = timedelta_seconds(86400); td.days"#)
1034 .unwrap_or_default(),
1035 1 as rhai::INT,
1036 "we should be getting 1"
1037 );
1038
1039 assert_eq!(
1041 engine
1042 .eval::<rhai::INT>(r#"let td = timedelta_days(14); td.weeks"#)
1043 .unwrap_or_default(),
1044 2 as rhai::INT,
1045 "we should be getting 2"
1046 );
1047
1048 assert_eq!(
1050 engine
1051 .eval::<rhai::INT>(r#"let td = timedelta_seconds(7); td.milliseconds"#)
1052 .unwrap_or_default(),
1053 7000 as rhai::INT,
1054 "we should be getting 7000"
1055 );
1056
1057 assert_eq!(
1059 engine
1060 .eval::<rhai::INT>(r#"let td = timedelta_seconds(7); td.microseconds"#)
1061 .unwrap_or_default(),
1062 7000000 as rhai::INT,
1063 "we should be getting 7000000"
1064 );
1065
1066 assert_eq!(
1068 engine
1069 .eval::<rhai::INT>(r#"let td = timedelta_seconds(7); td.nanoseconds"#)
1070 .unwrap_or_default(),
1071 7000000000 as rhai::INT,
1072 "we should be getting 7000000000"
1073 );
1074 }
1075
1076 #[test]
1077 fn it_craps() {
1078 let engine = get_engine();
1079
1080 let bad_timestamp_rfc2822 = "Wed, Aug 9 1989 09:30:11";
1081
1082 assert!(
1084 engine
1085 .eval::<String>(&format!(r#"datetime_rfc2822("{}")"#, bad_timestamp_rfc2822))
1086 .is_err(),
1087 "we should be getting parse error"
1088 );
1089 }
1090}