1#![cfg_attr(not(feature = "std"), no_std)]
46#![cfg_attr(doc_cfg, feature(doc_cfg))]
47
48use chrono::*;
49
50const HOUR_TO_SEC: i32 = 3600;
51const MIN_TO_SEC: i32 = 60;
52pub mod known_timezones;
53#[cfg(feature = "serde")]
54#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
55pub mod serde;
56
57#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
65pub struct TimeZoneZst<const HOUR: i32, const MINUTE: u32>;
66
67#[deprecated(since = "0.2.0", note = "Use `TimeZoneZst` instead.")]
68pub type UtcZst<const HOUR: i32, const MINUTE: u32> = TimeZoneZst<HOUR, MINUTE>;
69
70impl<const HOUR: i32, const MINUTE: u32> TimeZoneZst<HOUR, MINUTE> {
71 pub const OFFSET_SECS: i32 =
73 HOUR * HOUR_TO_SEC + if HOUR < 0 { -1 } else { 1 } * (MINUTE as i32) * MIN_TO_SEC;
74 pub const IS_IN_VALID_RANGE: bool = (HOUR >= -23) & (HOUR <= 23) & (MINUTE < 60);
76 pub const FIXED_OFFSET: FixedOffset = match (
78 FixedOffset::east_opt(Self::OFFSET_SECS),
79 Self::IS_IN_VALID_RANGE,
80 ) {
81 (Some(fix), true) => fix,
82 _ => panic!("Invalid TimeZone"),
83 };
84 pub const fn new() -> Self {
86 let _ = Self::FIXED_OFFSET;
88 TimeZoneZst
89 }
90 #[cfg(feature = "clock")]
91 #[deprecated(since = "0.3.0")]
92 #[allow(deprecated)]
93 pub fn today() -> Date<Self> {
95 Utc::today().with_timezone(&Self::new())
96 }
97 #[cfg(feature = "clock")]
98 pub fn now() -> DateTime<Self> {
100 Utc::now().with_timezone(&Self::new())
101 }
102}
103
104impl<const HOUR: i32, const MINUTE: u32> Offset for TimeZoneZst<HOUR, MINUTE> {
105 fn fix(&self) -> FixedOffset {
106 Self::FIXED_OFFSET
107 }
108}
109
110impl<const HOUR: i32, const MINUTE: u32> TimeZone for TimeZoneZst<HOUR, MINUTE> {
111 type Offset = Self;
112 fn from_offset(offset: &Self::Offset) -> Self {
113 *offset
114 }
115 fn offset_from_local_date(&self, _local: &NaiveDate) -> LocalResult<Self::Offset> {
116 LocalResult::Single(*self)
117 }
118 fn offset_from_local_datetime(&self, _local: &NaiveDateTime) -> LocalResult<Self::Offset> {
119 LocalResult::Single(*self)
120 }
121 fn offset_from_utc_date(&self, _utc: &NaiveDate) -> Self::Offset {
122 *self
123 }
124 fn offset_from_utc_datetime(&self, _utc: &NaiveDateTime) -> Self::Offset {
125 *self
126 }
127}
128
129impl<const HOUR: i32, const MINUTE: u32> Default for TimeZoneZst<HOUR, MINUTE> {
130 fn default() -> Self {
131 Self::new()
132 }
133}
134
135impl<const HOUR: i32, const MINUTE: u32> core::fmt::Debug for TimeZoneZst<HOUR, MINUTE> {
136 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
137 write!(f, "{:+03}:{:02}", HOUR, MINUTE)
138 }
139}
140
141impl<const HOUR: i32, const MINUTE: u32> core::fmt::Display for TimeZoneZst<HOUR, MINUTE> {
142 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
143 write!(f, "{:+03}:{:02}", HOUR, MINUTE)
144 }
145}
146
147#[cfg(test)]
148#[cfg(feature = "std")]
149mod tests {
150 use crate::known_timezones::*;
151 use crate::*;
152 #[test]
153 fn display() {
154 let p9 = UtcP9::default();
155 assert_eq!(&p9.to_string(), "+09:00");
156 assert_eq!(std::mem::size_of_val(&p9), 0);
157 assert_eq!(UtcP9::IS_IN_VALID_RANGE, true);
158 let n = p9.with_ymd_and_hms(2000, 1, 1, 12, 00, 00).unwrap();
159 assert_eq!(
160 n.naive_utc(),
161 NaiveDate::from_ymd_opt(2000, 1, 1)
162 .unwrap()
163 .and_hms_opt(3, 0, 0)
164 .unwrap()
165 );
166 let m9 = UtcM9::default();
167 assert_eq!(&m9.to_string(), "-09:00");
168 let n = m9.with_ymd_and_hms(2000, 1, 1, 12, 00, 00).unwrap();
169 assert_eq!(
170 n.naive_utc(),
171 NaiveDate::from_ymd_opt(2000, 1, 1)
172 .unwrap()
173 .and_hms_opt(21, 0, 0)
174 .unwrap()
175 );
176 let p9 = UtcP9_30::default();
177 let n = p9.with_ymd_and_hms(2000, 1, 1, 12, 00, 00).unwrap();
178 assert_eq!(
179 n.naive_utc(),
180 NaiveDate::from_ymd_opt(2000, 1, 1)
181 .unwrap()
182 .and_hms_opt(2, 30, 0)
183 .unwrap()
184 );
185 let m9 = UtcM9_30::default();
186 let n = m9.with_ymd_and_hms(2000, 1, 1, 12, 00, 00).unwrap();
187 assert_eq!(
188 n.naive_utc(),
189 NaiveDate::from_ymd_opt(2000, 1, 1)
190 .unwrap()
191 .and_hms_opt(21, 30, 0)
192 .unwrap()
193 );
194 }
195}