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