rhai_chrono/
lib.rs

1use rhai::def_package;
2use rhai::plugin::*;
3
4pub(crate) mod datetime;
5pub(crate) mod timedelta;
6
7def_package! {
8    /// Package for chrono datetime usage.
9    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        // test init now
57        assert!(
58            engine.eval::<DateTimeFixed>(r#"datetime_now()"#).is_ok(),
59            "we should be getting Utc::now()"
60        );
61
62        // test init utc
63        assert!(
64            engine.eval::<DateTimeFixed>(r#"datetime_utc()"#).is_ok(),
65            "we should be getting Utc::now()"
66        );
67
68        // test init local
69        assert!(
70            engine.eval::<DateTimeFixed>(r#"datetime_local()"#).is_ok(),
71            "we should be getting Local::now()"
72        );
73
74        // test to_string from utc
75        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        // test to string from local
81        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        // test init from unix timestamp
87        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        // test init from unix millis
96        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        // test init from unix micros
105        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        // test init from unix nanos
114        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        // test init from rfc2822
123        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        // test init from rfc3339
132        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        // test init from string and format
141        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        // test to_rfc3339 from utc
153        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        // test to_rfc3339
159        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        // test to_rfc2822
165        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        // test timestamp
174        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        // test timestamp_millis
183        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        // test timestamp_micros
195        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        // test timestamp_nanos
207        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        // test timestamp_subsec_millis
219        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        // test timestamp_subsec_micros
231        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        // test timestamp_subsec_nanos
243        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        // test years_since
255        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        // test format
306        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        // test format + locale
318        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        // test with timezone local
330        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        // test with timezone local
345        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        // test with IANA timezone
357        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        // test with IANA timezone
372        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        // test with offset for timezone
384        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        // test with offset for timezone
399        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        // test with offset for timezone
411        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        // test with time
423        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        // test with time
439        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        // test ordinal
451        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        // test ordinal
467        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        // test ordinal0
476        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        // test ordinal0
492        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        // test year
504        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        // test year
520        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        // test month
529        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        // test month
545        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        // test month0
554        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        // test month0
570        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        // test day
582        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        // test day
598        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        // test day0
607        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        // test day0
622        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        // test hour
634        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        // test hour
650        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        // test minute
659        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        // test second
683        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        // test nanosecond
710        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        // test add days
737        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        // test sub days
753        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        // test add months
769        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        // test sub months
785        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        // test diff
801        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        // test add_timedelta
820        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        // test sub_timedelta
839        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        // test init zero
858        assert!(
859            engine.eval::<Timedelta>(r#"timedelta_zero()"#).is_ok(),
860            "we should be getting zero timedelta"
861        );
862
863        // test init zero
864        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        // test init zero
873        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        // test init min
882        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        // test init max
889        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        // test init seconds
896        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        // test init seconds and nanos
905        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        // test init seconds and nanos
914        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        // test init days
923        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        // test init weeks
932        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        // test init hours
941        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        // test init minutes
950        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        // test init milliseconds
959        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        // test init microseconds
968        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        // test init nanoseconds
977        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        // test abs
986        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        // test add
995        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        // test sub
1004        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        // test minutes
1013        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        // test hours
1022        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        // test days
1031        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        // test weeks
1040        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        // test milliseconds
1049        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        // test microseconds
1058        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        // test nanoseconds
1067        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        // test init from rfc2822
1083        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}