rustbasic_core/
chrono_tz.rs1use std::str::FromStr;
2use crate::chrono::{FixedOffset, TimeZone, Offset};
3
4#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
5pub enum Tz {
6 Utc,
7 Fixed(FixedOffset),
8}
9
10pub const UTC: Tz = Tz::Utc;
11
12impl FromStr for Tz {
13 type Err = &'static str;
14
15 fn from_str(s: &str) -> Result<Self, Self::Err> {
16 let s = s.trim();
17 if s.eq_ignore_ascii_case("utc") || s.eq_ignore_ascii_case("gmt") || s.is_empty() {
18 return Ok(Tz::Utc);
19 }
20 if let Some(offset) = parse_offset_string(s) {
21 return Ok(Tz::Fixed(offset));
22 }
23 match s {
24 "Asia/Jakarta" | "WIB" => Ok(Tz::Fixed(FixedOffset::east_opt(7 * 3600).unwrap())),
25 "Asia/Singapore" | "Asia/Kuala_Lumpur" | "Asia/Makassar" | "WITA" => {
26 Ok(Tz::Fixed(FixedOffset::east_opt(8 * 3600).unwrap()))
27 }
28 "Asia/Jayapura" | "WIT" => Ok(Tz::Fixed(FixedOffset::east_opt(9 * 3600).unwrap())),
29 "Asia/Bangkok" => Ok(Tz::Fixed(FixedOffset::east_opt(7 * 3600).unwrap())),
30 "Asia/Tokyo" | "Asia/Seoul" => Ok(Tz::Fixed(FixedOffset::east_opt(9 * 3600).unwrap())),
31 "America/New_York" | "EST" => Ok(Tz::Fixed(FixedOffset::west_opt(5 * 3600).unwrap())),
32 "America/Chicago" | "CST" => Ok(Tz::Fixed(FixedOffset::west_opt(6 * 3600).unwrap())),
33 "America/Denver" | "MST" => Ok(Tz::Fixed(FixedOffset::west_opt(7 * 3600).unwrap())),
34 "America/Los_Angeles" | "PST" => Ok(Tz::Fixed(FixedOffset::west_opt(8 * 3600).unwrap())),
35 "Europe/London" | "GMT" => Ok(Tz::Fixed(FixedOffset::east_opt(0).unwrap())),
36 _ => {
37 Ok(Tz::Fixed(FixedOffset::east_opt(7 * 3600).unwrap())) }
39 }
40 }
41}
42
43fn parse_offset_string(s: &str) -> Option<FixedOffset> {
44 let s = s.trim();
45 if s.is_empty() { return None; }
46 let sign = match s.chars().next()? {
47 '+' => 1,
48 '-' => -1,
49 _ => return None,
50 };
51 let rest = &s[1..];
52 let parts: Vec<&str> = rest.split(':').collect();
53 if parts.len() == 2 {
54 let hours: i32 = parts[0].parse().ok()?;
55 let minutes: i32 = parts[1].parse().ok()?;
56 FixedOffset::east_opt(sign * (hours * 3600 + minutes * 60))
57 } else if parts.len() == 1 {
58 if rest.len() == 4 {
59 let hours: i32 = rest[0..2].parse().ok()?;
60 let minutes: i32 = rest[2..4].parse().ok()?;
61 FixedOffset::east_opt(sign * (hours * 3600 + minutes * 60))
62 } else if rest.len() == 2 || rest.len() == 1 {
63 let hours: i32 = rest.parse().ok()?;
64 FixedOffset::east_opt(sign * hours * 3600)
65 } else {
66 None
67 }
68 } else {
69 None
70 }
71}
72
73impl TimeZone for Tz {
74 type Offset = TzOffset;
75
76 fn from_offset(offset: &Self::Offset) -> Self {
77 match offset {
78 TzOffset::Utc => Tz::Utc,
79 TzOffset::Fixed(fo) => Tz::Fixed(*fo),
80 }
81 }
82
83 fn offset_from_local_date(&self, _local: &crate::chrono::NaiveDate) -> crate::chrono::LocalResult<Self::Offset> {
84 match self {
85 Tz::Utc => crate::chrono::LocalResult::Single(TzOffset::Utc),
86 Tz::Fixed(fo) => crate::chrono::LocalResult::Single(TzOffset::Fixed(*fo)),
87 }
88 }
89
90 fn offset_from_local_datetime(&self, _local: &crate::chrono::NaiveDateTime) -> crate::chrono::LocalResult<Self::Offset> {
91 match self {
92 Tz::Utc => crate::chrono::LocalResult::Single(TzOffset::Utc),
93 Tz::Fixed(fo) => crate::chrono::LocalResult::Single(TzOffset::Fixed(*fo)),
94 }
95 }
96
97 fn offset_from_utc_date(&self, _utc: &crate::chrono::NaiveDate) -> Self::Offset {
98 match self {
99 Tz::Utc => TzOffset::Utc,
100 Tz::Fixed(fo) => TzOffset::Fixed(*fo),
101 }
102 }
103
104 fn offset_from_utc_datetime(&self, _utc: &crate::chrono::NaiveDateTime) -> Self::Offset {
105 match self {
106 Tz::Utc => TzOffset::Utc,
107 Tz::Fixed(fo) => TzOffset::Fixed(*fo),
108 }
109 }
110}
111
112#[derive(Copy, Clone, Debug, PartialEq, Eq)]
113pub enum TzOffset {
114 Utc,
115 Fixed(FixedOffset),
116}
117
118impl Offset for TzOffset {
119 fn fix(&self) -> FixedOffset {
120 match self {
121 TzOffset::Utc => FixedOffset::east_opt(0).unwrap(),
122 TzOffset::Fixed(fo) => *fo,
123 }
124 }
125}
126
127impl std::fmt::Display for TzOffset {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 write!(f, "{}", self.fix())
130 }
131}