use crate::Duration;
use super::pyastrotime::PyAstroTime;
use pyo3::prelude::*;
use pyo3::types::PyBytes;
use pyo3::types::PyDict;
#[pyclass(name = "duration", module = "satkit")]
#[derive(Clone)]
pub struct PyDuration {
pub inner: Duration,
}
#[pymethods]
impl PyDuration {
#[new]
#[pyo3(signature=(**kwargs))]
fn py_new(kwargs: Option<Bound<'_, PyDict>>) -> PyResult<Self> {
let mut days = 0.0;
let mut seconds = 0.0;
let mut minutes = 0.0;
let mut hours = 0.0;
if let Some(kwargs) = kwargs {
if let Some(d) = kwargs.get_item("days")? {
days = d.extract::<f64>()?;
}
if let Some(s) = kwargs.get_item("seconds")? {
seconds = s.extract::<f64>()?;
}
if let Some(m) = kwargs.get_item("minutes")? {
minutes = m.extract::<f64>()?;
}
if let Some(h) = kwargs.get_item("hours")? {
hours = h.extract::<f64>()?;
}
}
Ok(PyDuration {
inner: Duration::Seconds(seconds)
+ Duration::Days(days)
+ Duration::Minutes(minutes)
+ Duration::Hours(hours),
})
}
#[staticmethod]
fn from_days(d: f64) -> PyDuration {
PyDuration {
inner: Duration::Days(d),
}
}
#[staticmethod]
fn from_seconds(d: f64) -> PyDuration {
PyDuration {
inner: Duration::Seconds(d),
}
}
#[staticmethod]
fn from_minutes(d: f64) -> PyDuration {
PyDuration {
inner: Duration::Minutes(d),
}
}
#[staticmethod]
fn from_hours(d: f64) -> PyDuration {
PyDuration {
inner: Duration::Hours(d),
}
}
fn __add__(&self, other: &Bound<'_, PyAny>) -> PyResult<PyObject> {
if other.is_instance_of::<PyDuration>() {
let dur = other.extract::<PyDuration>()?;
pyo3::Python::with_gil(|py| -> PyResult<PyObject> {
Ok(PyDuration {
inner: self.inner.clone() + dur.inner.clone(),
}
.into_py(py))
})
} else if other.is_instance_of::<PyAstroTime>() {
let tm = other.extract::<PyAstroTime>()?;
pyo3::Python::with_gil(|py| -> PyResult<PyObject> {
Ok(PyAstroTime {
inner: tm.inner + self.inner.clone(),
}
.into_py(py))
})
} else {
Err(pyo3::exceptions::PyTypeError::new_err(
"Invalid right-hand side",
))
}
}
fn __sub__(&self, other: &PyDuration) -> PyDuration {
PyDuration {
inner: self.inner.clone() - other.inner.clone(),
}
}
fn __mul__(&self, other: f64) -> PyDuration {
PyDuration {
inner: Duration::Seconds(self.inner.seconds() * other),
}
}
fn days(&self) -> f64 {
self.inner.days()
}
fn seconds(&self) -> f64 {
self.inner.seconds()
}
fn minutes(&self) -> f64 {
self.inner.minutes()
}
fn hours(&self) -> f64 {
self.inner.hours()
}
fn __str__(&self) -> String {
self.inner.to_string()
}
fn __repr__(&self) -> String {
self.inner.to_string()
}
fn __setstate__(&mut self, py: Python, s: Py<PyBytes>) -> PyResult<()> {
let s = s.as_bytes(py);
if s.len() != 8 {
return Err(pyo3::exceptions::PyTypeError::new_err(
"Invalid serialization length",
));
}
let t = f64::from_le_bytes(s.try_into()?);
self.inner = Duration::Days(t);
Ok(())
}
fn __getstate__(&mut self, py: Python) -> PyResult<PyObject> {
Ok(PyBytes::new_bound(py, f64::to_le_bytes(self.inner.days()).as_slice()).to_object(py))
}
}