Skip to main content

_formatparse/datetime/
fixed_tz.rs

1use pyo3::prelude::*;
2use pyo3::IntoPyObjectExt;
3
4/// Fixed timezone offset for datetime parsing
5#[pyclass]
6pub struct FixedTzOffset {
7    offset_seconds: i32,
8    name: String,
9}
10
11#[pymethods]
12impl FixedTzOffset {
13    #[new]
14    fn new(offset_minutes: i32, name: String) -> Self {
15        Self {
16            offset_seconds: offset_minutes * 60,
17            name,
18        }
19    }
20
21    fn __repr__(&self) -> String {
22        let hours = self.offset_seconds.abs() / 3600;
23        let minutes = (self.offset_seconds.abs() % 3600) / 60;
24        let sign = if self.offset_seconds >= 0 { "" } else { "-" };
25        format!(
26            "<FixedTzOffset {} {}{}:{:02}:00>",
27            self.name, sign, hours, minutes
28        )
29    }
30
31    fn __str__(&self) -> String {
32        self.__repr__()
33    }
34
35    fn __eq__(&self, other: &Bound<'_, PyAny>) -> PyResult<bool> {
36        if let Ok(other_tz) = other.downcast::<Self>() {
37            Ok(self.offset_seconds == other_tz.borrow().offset_seconds
38                && self.name == other_tz.borrow().name)
39        } else {
40            Ok(false)
41        }
42    }
43
44    fn __ne__(&self, other: &Bound<'_, PyAny>) -> PyResult<bool> {
45        Ok(!self.__eq__(other)?)
46    }
47
48    /// Get the offset in seconds
49    #[getter]
50    fn offset(&self) -> i32 {
51        self.offset_seconds
52    }
53
54    /// Get the timezone name
55    #[getter]
56    fn name(&self) -> &str {
57        &self.name
58    }
59
60    /// tzinfo.utcoffset() - returns timedelta for offset
61    fn utcoffset(&self, py: Python, _dt: Option<&Bound<'_, PyAny>>) -> PyResult<PyObject> {
62        let datetime_module = py.import("datetime")?;
63        let timedelta_class = datetime_module.getattr("timedelta")?;
64        // timedelta(seconds=offset_seconds)
65        let delta = timedelta_class.call1((0, 0, self.offset_seconds))?;
66        delta.into_py_any(py)
67    }
68
69    /// tzinfo.dst() - returns None (no DST)
70    fn dst(&self, py: Python, _dt: Option<&Bound<'_, PyAny>>) -> PyResult<PyObject> {
71        Ok(py.None())
72    }
73
74    /// tzinfo.tzname() - returns timezone name
75    fn tzname(&self, _dt: Option<&Bound<'_, PyAny>>) -> String {
76        self.name.clone()
77    }
78}