polars_core/chunked_array/logical/
duration.rs

1use super::*;
2use crate::prelude::*;
3
4pub type DurationChunked = Logical<DurationType, Int64Type>;
5
6impl Int64Chunked {
7    pub fn into_duration(self, timeunit: TimeUnit) -> DurationChunked {
8        // SAFETY: no invalid states.
9        unsafe { DurationChunked::new_logical(self, DataType::Duration(timeunit)) }
10    }
11}
12
13impl LogicalType for DurationChunked {
14    fn dtype(&self) -> &DataType {
15        &self.dtype
16    }
17
18    fn get_any_value(&self, i: usize) -> PolarsResult<AnyValue<'_>> {
19        self.phys
20            .get_any_value(i)
21            .map(|av| av.as_duration(self.time_unit()))
22    }
23    unsafe fn get_any_value_unchecked(&self, i: usize) -> AnyValue<'_> {
24        self.phys
25            .get_any_value_unchecked(i)
26            .as_duration(self.time_unit())
27    }
28
29    fn cast_with_options(
30        &self,
31        dtype: &DataType,
32        cast_options: CastOptions,
33    ) -> PolarsResult<Series> {
34        use DataType::*;
35
36        use crate::datatypes::time_unit::TimeUnit::*;
37        match dtype {
38            Duration(tu) => {
39                let to_unit = *tu;
40                let (divisor, multiplier) = match (self.time_unit(), to_unit) {
41                    (Milliseconds, Microseconds) => (None, Some(1_000i64)),
42                    (Milliseconds, Nanoseconds) => (None, Some(1_000_000i64)),
43                    (Microseconds, Milliseconds) => (Some(1_000i64), None),
44                    (Microseconds, Nanoseconds) => (None, Some(1_000i64)),
45                    (Nanoseconds, Milliseconds) => (Some(1_000_000i64), None),
46                    (Nanoseconds, Microseconds) => (Some(1_000i64), None),
47                    _ => return Ok(self.clone().into_series()),
48                };
49
50                let out = match (divisor, multiplier) {
51                    (None, None) | (Some(_), Some(_)) => unreachable!(),
52                    (_, Some(multiplier)) => self.phys.as_ref().checked_mul_scalar(multiplier),
53                    (Some(divisor), _) => self.phys.as_ref().wrapping_trunc_div_scalar(divisor),
54                };
55                Ok(out.into_duration(to_unit).into_series())
56            },
57            dt if dt.is_primitive_numeric() => self.phys.cast_with_options(dtype, cast_options),
58            dt => {
59                polars_bail!(
60                    InvalidOperation:
61                    "casting from {:?} to {:?} not supported",
62                    self.dtype(), dt
63                )
64            },
65        }
66    }
67}