polars_core/chunked_array/logical/
datetime.rs1use super::*;
2use crate::datatypes::time_unit::TimeUnit;
3use crate::prelude::*;
4
5pub type DatetimeChunked = Logical<DatetimeType, Int64Type>;
6
7impl Int64Chunked {
8 pub fn into_datetime(self, timeunit: TimeUnit, tz: Option<TimeZone>) -> DatetimeChunked {
9 unsafe { DatetimeChunked::new_logical(self, DataType::Datetime(timeunit, tz)) }
11 }
12}
13
14impl LogicalType for DatetimeChunked {
15 fn dtype(&self) -> &DataType {
16 &self.dtype
17 }
18
19 fn get_any_value(&self, i: usize) -> PolarsResult<AnyValue<'_>> {
20 self.phys
21 .get_any_value(i)
22 .map(|av| av.as_datetime(self.time_unit(), self.time_zone().as_ref()))
23 }
24
25 unsafe fn get_any_value_unchecked(&self, i: usize) -> AnyValue<'_> {
26 self.phys
27 .get_any_value_unchecked(i)
28 .as_datetime(self.time_unit(), self.time_zone().as_ref())
29 }
30
31 fn cast_with_options(
32 &self,
33 dtype: &DataType,
34 cast_options: CastOptions,
35 ) -> PolarsResult<Series> {
36 use DataType::*;
37
38 use crate::datatypes::time_unit::TimeUnit::*;
39
40 let out = match dtype {
41 Datetime(to_unit, tz) => {
42 let from_unit = self.time_unit();
43 let (multiplier, divisor) = match (from_unit, to_unit) {
44 (Milliseconds, Nanoseconds) => (Some(1_000_000i64), None),
46 (Milliseconds, Microseconds) => (Some(1_000i64), None),
47 (Microseconds, Nanoseconds) => (Some(1_000i64), None),
48 (Nanoseconds, Milliseconds) => (None, Some(1_000_000i64)),
50 (Nanoseconds, Microseconds) => (None, Some(1_000i64)),
51 (Microseconds, Milliseconds) => (None, Some(1_000i64)),
52 _ => return self.phys.cast_with_options(dtype, cast_options),
53 };
54 match multiplier {
55 Some(m) => Ok((self.phys.as_ref().checked_mul_scalar(m))
57 .into_datetime(*to_unit, tz.clone())
58 .into_series()),
59 None => match divisor {
61 Some(d) => Ok(self
62 .phys
63 .apply_values(|v| v.div_euclid(d))
64 .into_datetime(*to_unit, tz.clone())
65 .into_series()),
66 None => unreachable!("must always have a time unit divisor here"),
67 },
68 }
69 },
70 #[cfg(feature = "dtype-date")]
71 Date => {
72 let cast_to_date = |tu_in_day: i64| {
73 let mut dt = self
74 .phys
75 .apply_values(|v| v.div_euclid(tu_in_day))
76 .cast_with_options(&Int32, cast_options)
77 .unwrap()
78 .into_date()
79 .into_series();
80 dt.set_sorted_flag(self.physical().is_sorted_flag());
81 Ok(dt)
82 };
83 match self.time_unit() {
84 Nanoseconds => cast_to_date(NS_IN_DAY),
85 Microseconds => cast_to_date(US_IN_DAY),
86 Milliseconds => cast_to_date(MS_IN_DAY),
87 }
88 },
89 #[cfg(feature = "dtype-time")]
90 Time => {
91 let (scaled_mod, multiplier) = match self.time_unit() {
92 Nanoseconds => (NS_IN_DAY, 1i64),
93 Microseconds => (US_IN_DAY, 1_000i64),
94 Milliseconds => (MS_IN_DAY, 1_000_000i64),
95 };
96 return Ok(self
97 .phys
98 .apply(|v| {
99 let t = (v? % scaled_mod).checked_mul(multiplier)?;
100 t.checked_add(NS_IN_DAY * (t < 0) as i64)
101 })
102 .into_time()
103 .into_series());
104 },
105 dt if dt.is_primitive_numeric() => {
106 return self.phys.cast_with_options(dtype, cast_options);
107 },
108 dt => {
109 polars_bail!(
110 InvalidOperation:
111 "casting from {:?} to {:?} not supported",
112 self.dtype(), dt
113 )
114 },
115 };
116 out.map(|mut s| {
117 s.set_sorted_flag(self.physical().is_sorted_flag());
120 s
121 })
122 }
123}