1use crate::tackler;
12use jiff::Zoned;
13use jiff::fmt::strtime;
14use jiff::tz::{Offset, TimeZone};
15
16pub static TZ_UTC: Offset = jiff::tz::Offset::UTC;
18
19#[derive(Debug, Copy, Clone, Default)]
21pub enum TimestampStyle {
22 Date,
24 Secodns,
26 #[default]
30 Full,
31}
32
33impl TimestampStyle {
34 pub const DATE: &'static str = "date";
36
37 pub const SECONDS: &'static str = "seconds";
39
40 pub const FULL: &'static str = "full";
42
43 pub fn from(name: &str) -> Result<Self, tackler::Error> {
49 match name {
50 TimestampStyle::DATE => Ok(TimestampStyle::Date),
51 TimestampStyle::SECONDS => Ok(TimestampStyle::Secodns),
52 TimestampStyle::FULL => Ok(TimestampStyle::Full),
53 _ => Err(format!(
54 "Unknown timestamp style: '{name}'. Valid options are: {}, {}, {}",
55 Self::DATE,
56 Self::SECONDS,
57 Self::FULL
58 )
59 .into()),
60 }
61 }
62}
63
64#[derive(Debug, Clone, Copy, Default)]
66pub enum GroupBy {
67 Year,
69 #[default]
72 Month,
73 Date,
75 IsoWeek,
77 IsoWeekDate,
79}
80
81impl GroupBy {
82 pub const YEAR: &'static str = "year";
84
85 pub const MONTH: &'static str = "month";
87
88 pub const DATE: &'static str = "date";
90
91 pub const ISO_WEEK: &'static str = "iso-week";
93
94 pub const ISO_WEEK_DATE: &'static str = "iso-week-date";
96
97 pub fn from(group_by: &str) -> Result<GroupBy, tackler::Error> {
103 match group_by {
104 GroupBy::ISO_WEEK_DATE => Ok(GroupBy::IsoWeekDate),
105 GroupBy::ISO_WEEK => Ok(GroupBy::IsoWeek),
106 GroupBy::DATE => Ok(GroupBy::Date),
107 GroupBy::MONTH => Ok(GroupBy::Month),
108 GroupBy::YEAR => Ok(GroupBy::Year),
109 _ => {
110 let msg = format!(
111 "Unknown group-by selector: '{group_by}'. Valid options are: {}, {}, {}, {}, {}",
112 GroupBy::ISO_WEEK_DATE,
113 GroupBy::ISO_WEEK,
114 GroupBy::DATE,
115 GroupBy::MONTH,
116 GroupBy::YEAR
117 );
118 Err(msg.into())
119 }
120 }
121 }
122}
123pub fn rfc3339_to_zoned(rfc3339_str: &str) -> Result<Zoned, tackler::Error> {
129 strtime::parse("%Y-%m-%dT%H:%M:%S%.f%:z", rfc3339_str)?
130 .to_zoned()
131 .map_err(|e| {
132 let msg = format!("Can't parse ts as rfc3339: '{rfc3339_str}', error: {e}");
133 msg.into()
134 })
135}
136#[must_use]
152pub fn rfc_3339(ts: &Zoned) -> String {
153 strtime::format("%Y-%m-%dT%H:%M:%S%.f%:z", ts)
154 .unwrap_or_else(|err| format!("IE: rfc_3339, frmt error: {err}"))
155}
156
157#[must_use]
175pub fn seconds_tz(ts: &Zoned) -> String {
176 strtime::format("%Y-%m-%d %H:%M:%S %:z", ts)
177 .unwrap_or_else(|err| format!("IE: seconds_tz, frmt error: {err}"))
178}
179
180#[must_use]
198pub fn full_tz(ts: &Zoned) -> String {
199 strtime::format("%Y-%m-%d %H:%M:%S%.f %:z", ts)
200 .unwrap_or_else(|err| format!("IE: full_tz, frmt error: {err}"))
201}
202
203fn fmt_seconds(ts: &Zoned) -> String {
204 strtime::format("%Y-%m-%d %H:%M:%S", ts)
205 .unwrap_or_else(|err| format!("IE: fmt_seconds, frmt error: {err}"))
206}
207
208fn fmt_full(ts: &Zoned) -> String {
209 strtime::format("%Y-%m-%d %H:%M:%S%.f", ts)
210 .unwrap_or_else(|err| format!("IE: fmt_full, frmt error: {err}"))
211}
212
213fn fmt_date(ts: &Zoned) -> String {
214 strtime::format("%Y-%m-%d", ts).unwrap_or_else(|err| format!("IE: fmt_date, frmt error: {err}"))
215}
216
217fn fmt_month(ts: &Zoned) -> String {
218 strtime::format("%Y-%m", ts).unwrap_or_else(|err| format!("IE: fmt_month, frmt error: {err}"))
219}
220
221fn fmt_year(ts: &Zoned) -> String {
222 strtime::format("%Y", ts).unwrap_or_else(|err| format!("IE: fmt_year, frmt error: {err}"))
223}
224
225fn fmt_week(ts: &Zoned) -> String {
226 let iso_date = ts.date().iso_week_date();
227 let y = iso_date.year();
228 let w = iso_date.week();
229
230 format!("{y}-W{w:02}")
231}
232
233fn fmt_week_date(ts: &Zoned) -> String {
234 let iso_date = ts.date().iso_week_date();
235 let y = iso_date.year();
236 let w = iso_date.week();
237 let wd = iso_date.weekday().to_monday_one_offset();
238
239 format!("{y}-W{w:02}-{wd}")
240}
241
242#[must_use]
260pub fn as_utc_seconds(ts: &Zoned) -> String {
261 fmt_seconds(&ts.with_time_zone(TZ_UTC.to_time_zone().clone()))
262}
263
264#[must_use]
283pub fn as_utc_full(ts: &Zoned) -> String {
284 fmt_full(&ts.with_time_zone(TZ_UTC.to_time_zone().clone()))
285}
286
287#[must_use]
303pub fn as_utc_date(ts: &Zoned) -> String {
304 fmt_date(&ts.with_time_zone(TZ_UTC.to_time_zone().clone()))
305}
306
307#[must_use]
323pub fn as_utc_month(ts: &Zoned) -> String {
324 fmt_month(&ts.with_time_zone(TZ_UTC.to_time_zone().clone()))
325}
326
327#[must_use]
343pub fn as_utc_year(ts: &Zoned) -> String {
344 fmt_year(&ts.with_time_zone(TZ_UTC.to_time_zone().clone()))
345}
346
347#[must_use]
367pub fn as_utc_iso_week(ts: &Zoned) -> String {
368 fmt_week(&ts.with_time_zone(TZ_UTC.to_time_zone().clone()))
369}
370
371#[must_use]
391pub fn as_utc_iso_week_date(ts: &Zoned) -> String {
392 fmt_week_date(&ts.with_time_zone(TZ_UTC.to_time_zone().clone()))
393}
394
395#[must_use]
418pub fn as_tz_seconds(ts: &Zoned, tz: TimeZone) -> String {
419 fmt_seconds(&ts.with_time_zone(tz))
420}
421
422#[must_use]
445pub fn as_tz_full(ts: &Zoned, tz: TimeZone) -> String {
446 fmt_full(&ts.with_time_zone(tz))
447}
448
449#[must_use]
472pub fn as_tz_date(ts: &Zoned, tz: TimeZone) -> String {
473 fmt_date(&ts.with_time_zone(tz))
474}
475
476#[must_use]
499pub fn as_tz_month(ts: &Zoned, tz: TimeZone) -> String {
500 fmt_month(&ts.with_time_zone(tz))
501}
502
503#[must_use]
524pub fn as_tz_year(ts: &Zoned, tz: TimeZone) -> String {
525 fmt_year(&ts.with_time_zone(tz))
526}
527
528#[must_use]
548pub fn as_tz_iso_week(ts: &Zoned, tz: TimeZone) -> String {
549 fmt_week(&ts.with_time_zone(tz))
550}
551
552#[must_use]
572pub fn as_tz_iso_week_date(ts: &Zoned, tz: TimeZone) -> String {
573 fmt_week_date(&ts.with_time_zone(tz))
574}
575
576#[cfg(test)]
577mod tests {
578 use super::*;
579
580 #[test]
581 fn timestampstyle_full() {
583 let tss = TimestampStyle::from("full");
584 match tss {
585 Ok(TimestampStyle::Full) => (),
586 _ => panic!("/*:test:*/"),
587 }
588 }
589
590 #[test]
591 fn timestampstyle_seconds() {
593 let tss = TimestampStyle::from("seconds");
594 match tss {
595 Ok(TimestampStyle::Secodns) => (),
596 _ => panic!("/*:test:*/"),
597 }
598 }
599
600 #[test]
601 fn timestampstyle_date() {
603 let tss = TimestampStyle::from("date");
604 match tss {
605 Ok(TimestampStyle::Date) => (),
606 _ => panic!("/*:test:*/"),
607 }
608 }
609
610 #[test]
611 fn timestampstyle_invalid() {
613 let tss = TimestampStyle::from("minutes");
614 assert!(tss.is_err());
615 }
616
617 fn txt2ts(txt_ts: &str) -> Zoned {
618 strtime::parse("%Y-%m-%dT%H:%M:%S%.f%:z", txt_ts)
619 .unwrap()
620 .to_zoned()
621 .unwrap()
622 }
623
624 #[test]
625 fn doc_test() {
626 let ts = txt2ts("2022-12-24T13:14:15+02:00");
627 assert_eq!(rfc_3339(&ts), "2022-12-24T13:14:15+02:00");
628 }
629
630 #[test]
631 fn test_rfc_3339() {
632 assert_eq!(
633 rfc_3339(&txt2ts("2010-01-02T13:14:15+16:00")),
634 "2010-01-02T13:14:15+16:00"
635 );
636 assert_eq!(
637 rfc_3339(&txt2ts("2010-12-24T01:02:03.456+16:00")),
638 "2010-12-24T01:02:03.456+16:00"
639 );
640 assert_eq!(
641 rfc_3339(&txt2ts("2010-12-24T01:02:03.456789+16:00")),
642 "2010-12-24T01:02:03.456789+16:00"
643 );
644 assert_eq!(
645 rfc_3339(&txt2ts("2010-12-24T01:02:03.700-16:00")),
646 "2010-12-24T01:02:03.7-16:00"
647 );
648
649 assert_eq!(
650 rfc_3339(&txt2ts("2010-12-24T00:00:00+00:00")),
651 "2010-12-24T00:00:00+00:00"
652 );
653 assert_eq!(
654 rfc_3339(&txt2ts("2020-12-31T23:58:59+00:00")),
655 "2020-12-31T23:58:59+00:00"
656 );
657 assert_eq!(
658 rfc_3339(&txt2ts("2020-12-31T23:58:59+00:00")),
659 "2020-12-31T23:58:59+00:00"
660 );
661 }
662
663 #[test]
664 fn test_seconds_tz() {
665 assert_eq!(
666 seconds_tz(&txt2ts("2010-01-02T00:00:00+00:00")),
667 "2010-01-02 00:00:00 +00:00"
668 ); assert_eq!(
670 seconds_tz(&txt2ts("2010-12-24T13:14:15+16:00")),
671 "2010-12-24 13:14:15 +16:00"
672 );
673 assert_eq!(
674 seconds_tz(&txt2ts("2010-12-24T01:02:03.456+16:00")),
675 "2010-12-24 01:02:03 +16:00"
676 );
677 assert_eq!(
678 seconds_tz(&txt2ts("2010-12-24T01:02:03.456789+16:00")),
679 "2010-12-24 01:02:03 +16:00"
680 );
681 assert_eq!(
682 seconds_tz(&txt2ts("2020-12-24T23:58:59.123456789+00:00")),
683 "2020-12-24 23:58:59 +00:00"
684 ); assert_eq!(
686 seconds_tz(&txt2ts("2010-12-24T01:02:03.700-16:00")),
687 "2010-12-24 01:02:03 -16:00"
688 );
689
690 assert_eq!(
691 seconds_tz(&txt2ts("2020-12-31T23:58:59+00:00")),
692 "2020-12-31 23:58:59 +00:00"
693 );
694 }
695
696 #[test]
697 fn test_full_tz() {
698 assert_eq!(
699 full_tz(&txt2ts("2010-01-02T13:14:15+16:00")),
700 "2010-01-02 13:14:15 +16:00"
701 );
702 assert_eq!(
703 full_tz(&txt2ts("2010-12-24T01:02:03.456+16:00")),
704 "2010-12-24 01:02:03.456 +16:00"
705 );
706 assert_eq!(
707 full_tz(&txt2ts("2010-12-24T01:02:03.456789+16:00")),
708 "2010-12-24 01:02:03.456789 +16:00"
709 );
710 assert_eq!(
711 full_tz(&txt2ts("2010-12-24T01:02:03.700-16:00")),
712 "2010-12-24 01:02:03.7 -16:00"
713 );
714
715 assert_eq!(
716 full_tz(&txt2ts("2010-12-24T00:00:00+00:00")),
717 "2010-12-24 00:00:00 +00:00"
718 );
719 assert_eq!(
720 full_tz(&txt2ts("2020-12-31T23:58:59.123456789+00:00")),
721 "2020-12-31 23:58:59.123456789 +00:00"
722 );
723 }
724
725 #[test]
726 fn test_fmt_seconds() {
727 assert_eq!(
728 fmt_seconds(&txt2ts("2010-01-02T00:00:00+00:00")),
729 "2010-01-02 00:00:00"
730 );
731 assert_eq!(
732 fmt_seconds(&txt2ts("2010-12-24T13:14:15+16:00")),
733 "2010-12-24 13:14:15"
734 );
735 assert_eq!(
736 fmt_seconds(&txt2ts("2010-12-24T01:02:03.456+16:00")),
737 "2010-12-24 01:02:03"
738 );
739 assert_eq!(
740 fmt_seconds(&txt2ts("2010-12-24T01:02:03.456789+16:00")),
741 "2010-12-24 01:02:03"
742 );
743 assert_eq!(
744 fmt_seconds(&txt2ts("2020-12-24T23:58:59.123456789+00:00")),
745 "2020-12-24 23:58:59"
746 );
747 assert_eq!(
748 fmt_seconds(&txt2ts("2010-12-24T01:02:03.700-16:00")),
749 "2010-12-24 01:02:03"
750 );
751 }
752
753 #[test]
754 fn test_fmt_full() {
755 assert_eq!(
756 fmt_full(&txt2ts("2010-01-02T00:00:00+00:00")),
757 "2010-01-02 00:00:00"
758 );
759 assert_eq!(
760 fmt_full(&txt2ts("2010-12-24T13:14:15+16:00")),
761 "2010-12-24 13:14:15"
762 );
763 assert_eq!(
764 fmt_full(&txt2ts("2010-12-24T01:02:03.456+16:00")),
765 "2010-12-24 01:02:03.456"
766 );
767 assert_eq!(
768 fmt_full(&txt2ts("2010-12-24T01:02:03.456789+16:00")),
769 "2010-12-24 01:02:03.456789"
770 );
771 assert_eq!(
772 fmt_full(&txt2ts("2020-12-24T23:58:59.123456789+00:00")),
773 "2020-12-24 23:58:59.123456789"
774 );
775 assert_eq!(
776 fmt_full(&txt2ts("2010-12-24T01:02:03.700-16:00")),
777 "2010-12-24 01:02:03.7"
778 );
779 }
780
781 #[test]
782 fn test_fmt_date() {
783 assert_eq!(fmt_date(&txt2ts("2010-01-02T00:00:00+00:00")), "2010-01-02");
784 assert_eq!(fmt_date(&txt2ts("2010-12-24T13:14:15+16:00")), "2010-12-24");
785 assert_eq!(
786 fmt_date(&txt2ts("2010-12-24T01:02:03.456+16:00")),
787 "2010-12-24"
788 );
789 assert_eq!(
790 fmt_date(&txt2ts("2010-12-24T01:02:03.456789+16:00")),
791 "2010-12-24"
792 );
793 assert_eq!(
794 fmt_date(&txt2ts("2020-12-24T23:58:59.123456789+00:00")),
795 "2020-12-24"
796 );
797 assert_eq!(
798 fmt_date(&txt2ts("2010-12-24T01:02:03.700-16:00")),
799 "2010-12-24"
800 );
801 }
802
803 #[test]
804 fn test_fmt_month() {
805 assert_eq!(fmt_month(&txt2ts("2010-01-02T00:00:00+00:00")), "2010-01");
806 assert_eq!(fmt_month(&txt2ts("2010-12-24T13:14:15+16:00")), "2010-12");
807 assert_eq!(
808 fmt_month(&txt2ts("2010-12-24T01:02:03.456+16:00")),
809 "2010-12"
810 );
811 assert_eq!(
812 fmt_month(&txt2ts("2010-12-24T01:02:03.456789+16:00")),
813 "2010-12"
814 );
815 assert_eq!(
816 fmt_month(&txt2ts("2020-12-24T23:58:59.123456789+00:00")),
817 "2020-12"
818 );
819 assert_eq!(
820 fmt_month(&txt2ts("2010-12-24T01:02:03.700-16:00")),
821 "2010-12"
822 );
823 }
824
825 #[test]
826 fn test_fmt_year() {
827 assert_eq!(fmt_year(&txt2ts("2010-01-02T00:00:00+00:00")), "2010");
828 assert_eq!(fmt_year(&txt2ts("2010-12-24T13:14:15+16:00")), "2010");
829 assert_eq!(fmt_year(&txt2ts("2010-12-24T01:02:03.456+16:00")), "2010");
830 assert_eq!(
831 fmt_year(&txt2ts("2010-12-24T01:02:03.456789+16:00")),
832 "2010"
833 );
834 assert_eq!(
835 fmt_year(&txt2ts("2020-12-24T23:58:59.123456789+00:00")),
836 "2020"
837 );
838 assert_eq!(fmt_year(&txt2ts("2010-12-24T01:02:03.700-16:00")), "2010");
839 }
840
841 #[test]
842 fn test_fmt_week() {
843 assert_eq!(fmt_week(&txt2ts("2010-01-03T00:00:00+00:00")), "2009-W53");
844 assert_eq!(fmt_week(&txt2ts("2010-01-04T00:00:00+00:00")), "2010-W01");
845 assert_eq!(fmt_week(&txt2ts("2017-01-01T00:00:00+00:00")), "2016-W52");
846 assert_eq!(fmt_week(&txt2ts("2017-01-02T00:00:00+00:00")), "2017-W01");
847 }
848
849 #[test]
850 fn test_fmt_week_date() {
851 assert_eq!(
852 fmt_week_date(&txt2ts("2010-01-03T00:00:00+00:00")),
853 "2009-W53-7"
854 );
855 assert_eq!(
856 fmt_week_date(&txt2ts("2010-01-04T00:00:00+00:00")),
857 "2010-W01-1"
858 );
859 assert_eq!(
860 fmt_week_date(&txt2ts("2017-01-01T00:00:00+00:00")),
861 "2016-W52-7"
862 );
863
864 assert_eq!(
865 fmt_week_date(&txt2ts("2017-01-02T00:00:00+00:00")),
866 "2017-W01-1"
867 );
868
869 assert_eq!(
870 fmt_week_date(&txt2ts("2020-12-31T00:00:00+00:00")),
871 "2020-W53-4"
872 );
873 assert_eq!(
874 fmt_week_date(&txt2ts("2021-01-01T00:00:00+00:00")),
875 "2020-W53-5"
876 );
877 }
878
879 #[test]
880 fn test_utc_seconds() {
881 assert_eq!(
882 as_utc_seconds(&txt2ts("2010-01-01T00:00:00+16:00")),
883 "2009-12-31 08:00:00"
884 );
885 assert_eq!(
886 as_utc_seconds(&txt2ts("2010-01-02T14:15:16+00:00")),
887 "2010-01-02 14:15:16"
888 );
889 assert_eq!(
890 as_utc_seconds(&txt2ts("2010-01-01T01:02:03.700-16:00")),
891 "2010-01-01 17:02:03"
892 );
893 }
894
895 #[test]
896 fn test_utc_full() {
897 assert_eq!(
898 as_utc_full(&txt2ts("2010-01-01T00:00:00+16:00")),
899 "2009-12-31 08:00:00"
900 );
901 assert_eq!(
902 as_utc_full(&txt2ts("2010-01-02T14:15:16.456+00:00")),
903 "2010-01-02 14:15:16.456"
904 );
905 assert_eq!(
906 as_utc_full(&txt2ts("2010-01-01T01:02:03.700-16:00")),
907 "2010-01-01 17:02:03.7"
908 );
909
910 assert_eq!(
911 as_utc_full(&txt2ts("2020-12-31T23:58:59.123456789+00:00")),
912 "2020-12-31 23:58:59.123456789"
913 );
914
915 assert_eq!(
916 as_utc_full(&txt2ts("2020-12-31T23:58:59.123456789+00:00")),
917 "2020-12-31 23:58:59.123456789"
918 );
919 }
920
921 #[test]
922 fn test_utc_week() {
923 assert_eq!(
924 as_utc_iso_week(&txt2ts("2010-01-03T00:00:00+00:00")),
925 "2009-W53"
926 );
927 assert_eq!(
928 as_utc_iso_week(&txt2ts("2017-01-02T00:00:00+00:00")),
929 "2017-W01"
930 );
931 assert_eq!(
932 as_utc_iso_week(&txt2ts("2017-01-02T00:00:00+02:00")),
933 "2016-W52"
934 );
935 assert_eq!(
936 as_utc_iso_week(&txt2ts("2017-01-02T00:00:00-02:00")),
937 "2017-W01"
938 );
939 }
940
941 #[test]
942 fn test_utc_week_date() {
943 assert_eq!(
944 as_utc_iso_week_date(&txt2ts("2010-01-03T00:00:00+00:00")),
945 "2009-W53-7"
946 );
947
948 assert_eq!(
949 as_utc_iso_week_date(&txt2ts("2017-01-02T00:00:00+00:00")),
950 "2017-W01-1"
951 );
952 assert_eq!(
953 as_utc_iso_week_date(&txt2ts("2017-01-02T00:00:00+02:00")),
954 "2016-W52-7"
955 );
956 assert_eq!(
957 as_utc_iso_week_date(&txt2ts("2017-01-01T22:00:00+00:00")),
958 "2016-W52-7"
959 );
960 assert_eq!(
961 as_utc_iso_week_date(&txt2ts("2017-01-01T22:00:00-02:00")),
962 "2017-W01-1"
963 );
964 }
965
966 #[test]
967 fn test_utc_date() {
968 assert_eq!(
969 as_utc_date(&txt2ts("2010-01-01T15:00:00+16:00")),
970 "2009-12-31"
971 );
972 assert_eq!(
973 as_utc_date(&txt2ts("2010-01-01T08:02:03-16:00")),
974 "2010-01-02"
975 );
976 assert_eq!(
977 as_utc_date(&txt2ts("2020-12-31T23:59:59.999999999+00:00")),
978 "2020-12-31"
979 );
980 }
981
982 #[test]
983 fn test_utc_month() {
984 assert_eq!(
985 as_utc_month(&txt2ts("2010-01-01T15:00:00+16:00")),
986 "2009-12"
987 );
988 assert_eq!(
989 as_utc_month(&txt2ts("2010-01-31T08:02:03-16:00")),
990 "2010-02"
991 );
992 assert_eq!(
993 as_utc_month(&txt2ts("2020-12-31T23:59:59.999999999+00:00")),
994 "2020-12"
995 );
996 }
997
998 #[test]
999 fn test_utc_year() {
1000 assert_eq!(as_utc_year(&txt2ts("2010-01-01T15:00:00+16:00")), "2009");
1001 assert_eq!(as_utc_year(&txt2ts("2010-12-31T08:02:03-16:00")), "2011");
1002 assert_eq!(
1003 as_utc_year(&txt2ts("2020-12-31T23:59:59.999999999+00:00")),
1004 "2020"
1005 );
1006 }
1007
1008 #[test]
1009 fn test_zoned_seconds() {
1010 let utc_tz = TimeZone::get("UTC").unwrap();
1011 let helsinki_tz = TimeZone::get("Europe/Helsinki").unwrap();
1012
1013 assert_eq!(
1015 as_tz_seconds(&txt2ts("2010-01-02T00:00:00+00:00"), utc_tz.clone()),
1016 "2010-01-02 00:00:00"
1017 );
1018 assert_eq!(
1019 as_tz_seconds(&txt2ts("2010-01-02T00:00:00+00:00"), helsinki_tz.clone()),
1020 "2010-01-02 02:00:00"
1021 );
1022
1023 assert_eq!(
1025 as_tz_seconds(&txt2ts("2022-06-24T00:00:00+00:00"), utc_tz.clone()),
1026 "2022-06-24 00:00:00"
1027 );
1028 assert_eq!(
1029 as_tz_seconds(&txt2ts("2022-06-24T00:00:00+00:00"), helsinki_tz.clone()),
1030 "2022-06-24 03:00:00"
1031 );
1032
1033 assert_eq!(
1034 as_tz_seconds(&txt2ts("2010-01-02T00:00:00+16:00"), utc_tz),
1035 "2010-01-01 08:00:00"
1036 );
1037 assert_eq!(
1038 as_tz_seconds(&txt2ts("2010-01-02T00:00:00+16:00"), helsinki_tz),
1039 "2010-01-01 10:00:00"
1040 );
1041 }
1042
1043 #[test]
1044 fn test_zoned_full() {
1045 let utc_tz = TimeZone::get("UTC").unwrap();
1046 let helsinki_tz = TimeZone::get("Europe/Helsinki").unwrap();
1047
1048 assert_eq!(
1050 as_tz_full(&txt2ts("2010-01-02T00:00:00+00:00"), utc_tz.clone()),
1051 "2010-01-02 00:00:00"
1052 );
1053 assert_eq!(
1054 as_tz_full(&txt2ts("2010-01-02T00:00:00+00:00"), helsinki_tz.clone()),
1055 "2010-01-02 02:00:00"
1056 );
1057
1058 assert_eq!(
1060 as_tz_full(&txt2ts("2022-06-24T00:00:00+00:00"), utc_tz.clone()),
1061 "2022-06-24 00:00:00"
1062 );
1063 assert_eq!(
1064 as_tz_full(&txt2ts("2022-06-24T00:00:00+00:00"), helsinki_tz.clone()),
1065 "2022-06-24 03:00:00"
1066 );
1067
1068 assert_eq!(
1069 as_tz_full(&txt2ts("2010-01-02T00:00:00.123+16:00"), utc_tz),
1070 "2010-01-01 08:00:00.123"
1071 );
1072 assert_eq!(
1073 as_tz_full(&txt2ts("2010-01-02T00:00:00.123+16:00"), helsinki_tz),
1074 "2010-01-01 10:00:00.123"
1075 );
1076 }
1077
1078 #[test]
1079 fn test_zoned_date() {
1080 let utc_tz = TimeZone::get("UTC").unwrap();
1081 let helsinki_tz = TimeZone::get("Europe/Helsinki").unwrap();
1082
1083 assert_eq!(
1085 as_tz_date(&txt2ts("2010-01-02T00:00:00+00:00"), utc_tz.clone()),
1086 "2010-01-02"
1087 );
1088 assert_eq!(
1089 as_tz_date(
1090 &txt2ts("2009-12-31T21:59:59.999999999+00:00"),
1091 helsinki_tz.clone()
1092 ),
1093 "2009-12-31"
1094 );
1095 assert_eq!(
1096 as_tz_date(&txt2ts("2009-12-31T22:00:00+00:00"), helsinki_tz.clone()),
1097 "2010-01-01"
1098 );
1099
1100 assert_eq!(
1102 as_tz_date(&txt2ts("2022-06-24T00:00:00+00:00"), utc_tz),
1103 "2022-06-24"
1104 );
1105 assert_eq!(
1106 as_tz_date(&txt2ts("2022-06-23T21:00:00+00:00"), helsinki_tz),
1107 "2022-06-24"
1108 );
1109 }
1110
1111 #[test]
1112 fn test_zoned_month() {
1113 let utc_tz = TimeZone::get("UTC").unwrap();
1114 let helsinki_tz = TimeZone::get("Europe/Helsinki").unwrap();
1115
1116 assert_eq!(
1118 as_tz_month(&txt2ts("2010-01-02T00:00:00+00:00"), utc_tz.clone()),
1119 "2010-01"
1120 );
1121 assert_eq!(
1122 as_tz_month(
1123 &txt2ts("2009-12-31T21:59:59.999999999+00:00"),
1124 helsinki_tz.clone()
1125 ),
1126 "2009-12"
1127 );
1128 assert_eq!(
1129 as_tz_month(&txt2ts("2009-12-31T22:00:00+00:00"), helsinki_tz.clone()),
1130 "2010-01"
1131 );
1132
1133 assert_eq!(
1135 as_tz_month(&txt2ts("2022-06-30T00:00:00+00:00"), utc_tz),
1136 "2022-06"
1137 );
1138 assert_eq!(
1139 as_tz_month(&txt2ts("2022-06-30T21:00:00+00:00"), helsinki_tz),
1140 "2022-07"
1141 );
1142 }
1143
1144 #[test]
1145 fn test_zoned_year() {
1146 let utc_tz = TimeZone::get("UTC").unwrap();
1147 let helsinki_tz = TimeZone::get("Europe/Helsinki").unwrap();
1148
1149 assert_eq!(
1151 as_tz_year(&txt2ts("2010-01-02T00:00:00+00:00"), utc_tz),
1152 "2010"
1153 );
1154 assert_eq!(
1155 as_tz_year(
1156 &txt2ts("2009-12-31T21:59:59.999999999+00:00"),
1157 helsinki_tz.clone()
1158 ),
1159 "2009"
1160 );
1161 assert_eq!(
1162 as_tz_year(&txt2ts("2009-12-31T22:00:00+00:00"), helsinki_tz),
1163 "2010"
1164 );
1165 }
1166
1167 #[test]
1168 fn test_zoned_week() {
1169 let utc_tz = TimeZone::get("UTC").unwrap();
1170 let helsinki_tz = TimeZone::get("Europe/Helsinki").unwrap();
1171
1172 assert_eq!(
1174 as_tz_iso_week(&txt2ts("2010-01-03T00:00:00+00:00"), utc_tz.clone()),
1175 "2009-W53"
1176 );
1177 assert_eq!(
1178 as_tz_iso_week(
1179 &txt2ts("2010-01-03T21:59:59.999999999+00:00"),
1180 helsinki_tz.clone()
1181 ),
1182 "2009-W53"
1183 );
1184 assert_eq!(
1185 as_tz_iso_week(&txt2ts("2010-01-04T00:00:00+00:00"), utc_tz.clone()),
1186 "2010-W01"
1187 );
1188 assert_eq!(
1189 as_tz_iso_week(&txt2ts("2010-01-03T22:00:00+00:00"), helsinki_tz.clone()),
1190 "2010-W01"
1191 );
1192
1193 assert_eq!(
1195 as_tz_iso_week(
1196 &txt2ts("2022-06-19T23:59:59.999999999+00:00"),
1197 utc_tz.clone()
1198 ),
1199 "2022-W24"
1200 );
1201 assert_eq!(
1202 as_tz_iso_week(
1203 &txt2ts("2022-06-19T20:59:59.999999999+00:00"),
1204 helsinki_tz.clone()
1205 ),
1206 "2022-W24"
1207 );
1208 assert_eq!(
1209 as_tz_iso_week(&txt2ts("2022-06-20T00:00:00+00:00"), utc_tz.clone()),
1210 "2022-W25"
1211 );
1212 assert_eq!(
1213 as_tz_iso_week(&txt2ts("2022-06-19T21:00:00+00:00"), helsinki_tz.clone()),
1214 "2022-W25"
1215 );
1216 }
1217
1218 #[test]
1219 fn test_zoned_week_date() {
1220 let utc_tz = TimeZone::get("UTC").unwrap();
1221 let helsinki_tz = TimeZone::get("Europe/Helsinki").unwrap();
1222
1223 assert_eq!(
1225 as_tz_iso_week_date(&txt2ts("2010-01-03T00:00:00+00:00"), utc_tz.clone()),
1226 "2009-W53-7"
1227 );
1228 assert_eq!(
1229 as_tz_iso_week_date(
1230 &txt2ts("2010-01-03T21:59:59.999999999+00:00"),
1231 helsinki_tz.clone()
1232 ),
1233 "2009-W53-7"
1234 );
1235 assert_eq!(
1236 as_tz_iso_week_date(&txt2ts("2010-01-04T00:00:00+00:00"), utc_tz.clone()),
1237 "2010-W01-1"
1238 );
1239 assert_eq!(
1240 as_tz_iso_week_date(&txt2ts("2010-01-03T22:00:00+00:00"), helsinki_tz.clone()),
1241 "2010-W01-1"
1242 );
1243
1244 assert_eq!(
1246 as_tz_iso_week_date(
1247 &txt2ts("2022-06-19T23:59:59.999999999+00:00"),
1248 utc_tz.clone()
1249 ),
1250 "2022-W24-7"
1251 );
1252 assert_eq!(
1253 as_tz_iso_week_date(
1254 &txt2ts("2022-06-19T20:59:59.999999999+00:00"),
1255 helsinki_tz.clone()
1256 ),
1257 "2022-W24-7"
1258 );
1259 assert_eq!(
1260 as_tz_iso_week_date(&txt2ts("2022-06-20T00:00:00+00:00"), utc_tz.clone()),
1261 "2022-W25-1"
1262 );
1263 assert_eq!(
1264 as_tz_iso_week_date(&txt2ts("2022-06-19T21:00:00+00:00"), helsinki_tz.clone()),
1265 "2022-W25-1"
1266 );
1267 }
1268}