Skip to main content

temporal_rs/
sys.rs

1use crate::builtins::Now;
2use crate::host::HostClock;
3use crate::host::HostHooks;
4use crate::host::HostTimeZone;
5use crate::TemporalResult;
6
7use crate::unix_time::EpochNanoseconds;
8use crate::TemporalError;
9use crate::TimeZone;
10use timezone_provider::provider::TimeZoneProvider;
11use web_time::{SystemTime, UNIX_EPOCH};
12
13// TODO: Look into and potentially implement a `SystemTime` struct allows
14// providing closures or trait implementations that can then
15// be used to construct [`Now`]. Basically `Temporal` but with
16// traits or closures.
17//
18// Temporal could then be something like:
19//
20// pub struct Temporal(SystemTime<DefaultSystemClock, DefaultSystemTimeZone>)
21//
22
23/// The Temporal object for accessing current system time
24pub struct Temporal;
25
26impl Temporal {
27    /// Get a `Now` object for the default host system.
28    #[cfg(feature = "sys-local")]
29    #[deprecated(
30        since = "0.1.0",
31        note = "`now` deprecated was not clear about the host system implementation, please use `local_now`"
32    )]
33    pub fn now() -> Now<LocalHostSystem> {
34        Now::new(LocalHostSystem)
35    }
36
37    /// Get a `Now` object with a [`LocalHostSystem`], which
38    /// will use the host system's time zone as a fallback.
39    #[cfg(feature = "sys-local")]
40    pub fn local_now() -> Now<LocalHostSystem> {
41        Now::new(LocalHostSystem)
42    }
43
44    /// Get a `Now` object with a [`UtcHostSystem`], which
45    /// will use a UTC time zone as a fallback.
46    #[cfg(feature = "sys")]
47    pub fn utc_now() -> Now<UtcHostSystem> {
48        Now::new(UtcHostSystem)
49    }
50}
51
52/// A UTC host system implementation that will return the current time
53/// with the a UTC time zone as fallback.
54///
55/// This implementation is backed by [`std::time::SystemTime`].
56#[cfg(feature = "sys")]
57pub struct UtcHostSystem;
58
59#[cfg(feature = "sys")]
60impl HostHooks for UtcHostSystem {}
61
62#[cfg(feature = "sys")]
63impl HostClock for UtcHostSystem {
64    fn get_host_epoch_nanoseconds(&self) -> TemporalResult<EpochNanoseconds> {
65        get_system_nanoseconds()
66    }
67}
68
69#[cfg(feature = "sys")]
70impl HostTimeZone for UtcHostSystem {
71    fn get_host_time_zone(
72        &self,
73        provider: &(impl TimeZoneProvider + ?Sized),
74    ) -> TemporalResult<TimeZone> {
75        Ok(TimeZone::utc_with_provider(provider))
76    }
77}
78
79/// A local host system implementation that will return the current time
80/// with the system time zone as a fallback.
81///
82/// This implementation is backed by [`std::time::SystemTime`] and [`iana_time_zone`]
83#[cfg(feature = "sys-local")]
84pub struct LocalHostSystem;
85
86#[cfg(feature = "sys-local")]
87impl HostHooks for LocalHostSystem {}
88
89#[cfg(feature = "sys-local")]
90impl HostClock for LocalHostSystem {
91    fn get_host_epoch_nanoseconds(&self) -> TemporalResult<EpochNanoseconds> {
92        get_system_nanoseconds()
93    }
94}
95
96#[cfg(feature = "sys-local")]
97impl HostTimeZone for LocalHostSystem {
98    fn get_host_time_zone(
99        &self,
100        provider: &(impl TimeZoneProvider + ?Sized),
101    ) -> TemporalResult<TimeZone> {
102        get_system_timezone(provider)
103    }
104}
105
106#[cfg(feature = "sys-local")]
107#[inline]
108pub(crate) fn get_system_timezone(
109    provider: &(impl TimeZoneProvider + ?Sized),
110) -> TemporalResult<TimeZone> {
111    iana_time_zone::get_timezone()
112        .map(|s| TimeZone::try_from_identifier_str_with_provider(&s, provider))
113        .map_err(|_| TemporalError::general("Error fetching system time"))?
114}
115
116/// Returns the system time in nanoseconds.
117pub(crate) fn get_system_nanoseconds() -> TemporalResult<EpochNanoseconds> {
118    use crate::unix_time::EpochNanoseconds;
119
120    SystemTime::now()
121        .duration_since(UNIX_EPOCH)
122        .map_err(|_| TemporalError::general("Error fetching system time"))
123        .map(|d| EpochNanoseconds::from(d.as_nanos() as i128))
124}