Skip to main content

qubit_clock/
zoned.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! Timezone wrapper for clocks.
10//!
11//! This module provides [`Zoned`], a generic wrapper that adds timezone
12//! support to any clock implementation.
13//!
14//! # Author
15//!
16//! Haixing Hu
17
18use crate::{Clock, ZonedClock};
19use chrono::{DateTime, TimeZone, Utc};
20use chrono_tz::Tz;
21use std::ops::Deref;
22
23/// A wrapper that adds timezone support to any clock.
24///
25/// `Zoned<C>` wraps any clock implementing [`Clock`] and adds timezone
26/// functionality by implementing [`ZonedClock`]. It can convert UTC time to
27/// local time in the specified timezone.
28///
29/// # Deref Behavior
30///
31/// This type implements [`Deref`] to allow direct access to the wrapped
32/// clock's methods. This is particularly useful when wrapping controllable
33/// clocks like [`MockClock`](crate::MockClock).
34///
35/// # Examples
36///
37/// ```
38/// use qubit_clock::{Clock, ZonedClock, SystemClock, Zoned};
39/// use chrono_tz::Asia::Shanghai;
40///
41/// // Wrap a SystemClock with Shanghai timezone
42/// let clock = Zoned::new(SystemClock::new(), Shanghai);
43/// let local = clock.local_time();
44/// println!("Local time in Shanghai: {}", local);
45/// ```
46///
47/// ## Using with MockClock
48///
49/// ```
50/// use qubit_clock::{
51///     Clock, ZonedClock, ControllableClock, MockClock, Zoned
52/// };
53/// use chrono::{DateTime, Utc};
54/// use chrono_tz::Asia::Shanghai;
55///
56/// let mock = MockClock::new();
57/// let clock = Zoned::new(mock, Shanghai);
58///
59/// // Can use ZonedClock methods
60/// let local = clock.local_time();
61///
62/// // Can also use ControllableClock methods via Deref
63/// let time = DateTime::parse_from_rfc3339(
64///     "2024-01-01T00:00:00Z"
65/// ).unwrap().with_timezone(&Utc);
66/// clock.set_time(time);
67/// ```
68///
69/// # Author
70///
71/// Haixing Hu
72#[derive(Debug, Clone)]
73pub struct Zoned<C: Clock> {
74    /// The wrapped clock.
75    clock: C,
76    /// The timezone for this clock.
77    timezone: Tz,
78}
79
80impl<C: Clock> Zoned<C> {
81    /// Creates a new `Zoned` clock wrapping the given clock with the
82    /// specified timezone.
83    ///
84    /// # Arguments
85    ///
86    /// * `clock` - The clock to wrap.
87    /// * `timezone` - The timezone to use for local time conversions.
88    ///
89    /// # Returns
90    ///
91    /// A new `Zoned<C>` instance.
92    ///
93    /// # Examples
94    ///
95    /// ```
96    /// use qubit_clock::{SystemClock, Zoned};
97    /// use chrono_tz::Asia::Shanghai;
98    ///
99    /// let clock = Zoned::new(SystemClock::new(), Shanghai);
100    /// ```
101    ///
102    #[inline]
103    pub fn new(clock: C, timezone: Tz) -> Self {
104        Zoned { clock, timezone }
105    }
106
107    /// Returns a reference to the inner clock.
108    ///
109    /// # Returns
110    ///
111    /// A reference to the wrapped clock.
112    ///
113    /// # Examples
114    ///
115    /// ```
116    /// use qubit_clock::{Clock, SystemClock, Zoned};
117    /// use chrono_tz::Asia::Shanghai;
118    ///
119    /// let clock = Zoned::new(SystemClock::new(), Shanghai);
120    /// let inner = clock.inner();
121    /// let millis = inner.millis();
122    /// ```
123    ///
124    #[inline]
125    pub fn inner(&self) -> &C {
126        &self.clock
127    }
128
129    /// Consumes the `Zoned` wrapper and returns the inner clock.
130    ///
131    /// # Returns
132    ///
133    /// The wrapped clock.
134    ///
135    /// # Examples
136    ///
137    /// ```
138    /// use qubit_clock::{SystemClock, Zoned};
139    /// use chrono_tz::Asia::Shanghai;
140    ///
141    /// let clock = Zoned::new(SystemClock::new(), Shanghai);
142    /// let inner = clock.into_inner();
143    /// ```
144    ///
145    #[inline]
146    pub fn into_inner(self) -> C {
147        self.clock
148    }
149}
150
151impl<C: Clock> Clock for Zoned<C> {
152    #[inline]
153    fn millis(&self) -> i64 {
154        self.clock.millis()
155    }
156
157    #[inline]
158    fn time(&self) -> DateTime<Utc> {
159        self.clock.time()
160    }
161}
162
163impl<C: Clock> ZonedClock for Zoned<C> {
164    #[inline]
165    fn timezone(&self) -> Tz {
166        self.timezone
167    }
168
169    #[inline]
170    fn local_time(&self) -> DateTime<Tz> {
171        self.timezone.from_utc_datetime(&self.time().naive_utc())
172    }
173}
174
175impl<C: Clock> Deref for Zoned<C> {
176    type Target = C;
177
178    #[inline]
179    fn deref(&self) -> &Self::Target {
180        &self.clock
181    }
182}