ferroui_base/utilities/
time_zone_info.rs1use super::DateTime;
8use crate::animation::TimeSpan;
9use std::cell::RefCell;
10use std::rc::Rc;
11
12pub type LocalUtcOffsetProvider = Rc<dyn Fn(DateTime) -> TimeSpan>;
14
15crate::ferro_thread_local! {
16 static LOCAL_UTC_OFFSET_PROVIDER: RefCell<Option<LocalUtcOffsetProvider>> = const { RefCell::new(None) };
19}
20
21pub struct TimeZoneInfo;
23
24impl TimeZoneInfo {
25 pub const MAX_OFFSET: TimeSpan = TimeSpan::from_ticks(14 * TimeSpan::TICKS_PER_HOUR);
27
28 pub fn set_local_utc_offset_provider(provider: Option<LocalUtcOffsetProvider>) -> Option<LocalUtcOffsetProvider> {
31 LOCAL_UTC_OFFSET_PROVIDER.with(|current| current.replace(provider))
32 }
33
34 pub fn get_local_utc_offset(utc_time: DateTime) -> TimeSpan {
38 let provider = LOCAL_UTC_OFFSET_PROVIDER.with(|current| current.borrow().clone());
39 match provider {
40 Some(provider) => {
41 let ticks = provider(utc_time).ticks();
42 let ticks = ticks - ticks % TimeSpan::TICKS_PER_MINUTE;
43 TimeSpan::from_ticks(ticks.clamp(-Self::MAX_OFFSET.ticks(), Self::MAX_OFFSET.ticks()))
44 }
45 None => TimeSpan::ZERO,
46 }
47 }
48
49 pub fn get_utc_offset_of_local_time(local_time: DateTime) -> TimeSpan {
54 let first = Self::get_local_utc_offset(local_time);
55 if first == TimeSpan::ZERO && LOCAL_UTC_OFFSET_PROVIDER.with(|current| current.borrow().is_none()) {
56 return first;
57 }
58 let ticks = (local_time.ticks() - first.ticks()).clamp(DateTime::MIN_VALUE.ticks(), DateTime::MAX_VALUE.ticks());
59 Self::get_local_utc_offset(DateTime::from_ticks(ticks))
60 }
61}