polars_core/series/implementations/
datetime.rs

1use polars_compute::rolling::QuantileMethod;
2
3use super::*;
4#[cfg(feature = "algorithm_group_by")]
5use crate::frame::group_by::*;
6use crate::prelude::*;
7
8unsafe impl IntoSeries for DatetimeChunked {
9    fn into_series(self) -> Series {
10        Series(Arc::new(SeriesWrap(self)))
11    }
12}
13
14impl private::PrivateSeriesNumeric for SeriesWrap<DatetimeChunked> {
15    fn bit_repr(&self) -> Option<BitRepr> {
16        Some(self.0.physical().to_bit_repr())
17    }
18}
19
20impl private::PrivateSeries for SeriesWrap<DatetimeChunked> {
21    fn compute_len(&mut self) {
22        self.0.physical_mut().compute_len()
23    }
24    fn _field(&self) -> Cow<'_, Field> {
25        Cow::Owned(self.0.field())
26    }
27    fn _dtype(&self) -> &DataType {
28        self.0.dtype()
29    }
30    fn _get_flags(&self) -> StatisticsFlags {
31        self.0.physical().get_flags()
32    }
33    fn _set_flags(&mut self, flags: StatisticsFlags) {
34        self.0.physical_mut().set_flags(flags)
35    }
36
37    #[cfg(feature = "zip_with")]
38    fn zip_with_same_type(&self, mask: &BooleanChunked, other: &Series) -> PolarsResult<Series> {
39        let other = other.to_physical_repr().into_owned();
40        self.0
41            .physical()
42            .zip_with(mask, other.as_ref().as_ref())
43            .map(|ca| {
44                ca.into_datetime(self.0.time_unit(), self.0.time_zone().clone())
45                    .into_series()
46            })
47    }
48
49    fn into_total_eq_inner<'a>(&'a self) -> Box<dyn TotalEqInner + 'a> {
50        self.0.physical().into_total_eq_inner()
51    }
52    fn into_total_ord_inner<'a>(&'a self) -> Box<dyn TotalOrdInner + 'a> {
53        self.0.physical().into_total_ord_inner()
54    }
55
56    fn vec_hash(
57        &self,
58        random_state: PlSeedableRandomStateQuality,
59        buf: &mut Vec<u64>,
60    ) -> PolarsResult<()> {
61        self.0.physical().vec_hash(random_state, buf)?;
62        Ok(())
63    }
64
65    fn vec_hash_combine(
66        &self,
67        build_hasher: PlSeedableRandomStateQuality,
68        hashes: &mut [u64],
69    ) -> PolarsResult<()> {
70        self.0.physical().vec_hash_combine(build_hasher, hashes)?;
71        Ok(())
72    }
73
74    #[cfg(feature = "algorithm_group_by")]
75    unsafe fn agg_min(&self, groups: &GroupsType) -> Series {
76        self.0
77            .physical()
78            .agg_min(groups)
79            .into_datetime(self.0.time_unit(), self.0.time_zone().clone())
80            .into_series()
81    }
82
83    #[cfg(feature = "algorithm_group_by")]
84    unsafe fn agg_max(&self, groups: &GroupsType) -> Series {
85        self.0
86            .physical()
87            .agg_max(groups)
88            .into_datetime(self.0.time_unit(), self.0.time_zone().clone())
89            .into_series()
90    }
91    #[cfg(feature = "algorithm_group_by")]
92    unsafe fn agg_list(&self, groups: &GroupsType) -> Series {
93        // we cannot cast and dispatch as the inner type of the list would be incorrect
94        self.0
95            .physical()
96            .agg_list(groups)
97            .cast(&DataType::List(Box::new(self.dtype().clone())))
98            .unwrap()
99    }
100
101    fn subtract(&self, rhs: &Series) -> PolarsResult<Series> {
102        match (self.dtype(), rhs.dtype()) {
103            (DataType::Datetime(tu, tz), DataType::Datetime(tur, tzr)) => {
104                assert_eq!(tu, tur);
105                assert_eq!(tz, tzr);
106                let lhs = self.cast(&DataType::Int64, CastOptions::NonStrict).unwrap();
107                let rhs = rhs.cast(&DataType::Int64).unwrap();
108                Ok(lhs.subtract(&rhs)?.into_duration(*tu).into_series())
109            },
110            (DataType::Datetime(tu, tz), DataType::Duration(tur)) => {
111                assert_eq!(tu, tur);
112                let lhs = self.cast(&DataType::Int64, CastOptions::NonStrict).unwrap();
113                let rhs = rhs.cast(&DataType::Int64).unwrap();
114                Ok(lhs
115                    .subtract(&rhs)?
116                    .into_datetime(*tu, tz.clone())
117                    .into_series())
118            },
119            (dtl, dtr) => polars_bail!(opq = sub, dtl, dtr),
120        }
121    }
122    fn add_to(&self, rhs: &Series) -> PolarsResult<Series> {
123        match (self.dtype(), rhs.dtype()) {
124            (DataType::Datetime(tu, tz), DataType::Duration(tur)) => {
125                assert_eq!(tu, tur);
126                let lhs = self.cast(&DataType::Int64, CastOptions::NonStrict).unwrap();
127                let rhs = rhs.cast(&DataType::Int64).unwrap();
128                Ok(lhs
129                    .add_to(&rhs)?
130                    .into_datetime(*tu, tz.clone())
131                    .into_series())
132            },
133            (dtl, dtr) => polars_bail!(opq = add, dtl, dtr),
134        }
135    }
136    fn multiply(&self, rhs: &Series) -> PolarsResult<Series> {
137        polars_bail!(opq = mul, self.dtype(), rhs.dtype());
138    }
139    fn divide(&self, rhs: &Series) -> PolarsResult<Series> {
140        polars_bail!(opq = div, self.dtype(), rhs.dtype());
141    }
142    fn remainder(&self, rhs: &Series) -> PolarsResult<Series> {
143        polars_bail!(opq = rem, self.dtype(), rhs.dtype());
144    }
145    #[cfg(feature = "algorithm_group_by")]
146    fn group_tuples(&self, multithreaded: bool, sorted: bool) -> PolarsResult<GroupsType> {
147        self.0.physical().group_tuples(multithreaded, sorted)
148    }
149
150    fn arg_sort_multiple(
151        &self,
152        by: &[Column],
153        options: &SortMultipleOptions,
154    ) -> PolarsResult<IdxCa> {
155        self.0.physical().arg_sort_multiple(by, options)
156    }
157}
158
159impl SeriesTrait for SeriesWrap<DatetimeChunked> {
160    fn rename(&mut self, name: PlSmallStr) {
161        self.0.rename(name);
162    }
163
164    fn chunk_lengths(&self) -> ChunkLenIter<'_> {
165        self.0.physical().chunk_lengths()
166    }
167    fn name(&self) -> &PlSmallStr {
168        self.0.name()
169    }
170
171    fn chunks(&self) -> &Vec<ArrayRef> {
172        self.0.physical().chunks()
173    }
174    unsafe fn chunks_mut(&mut self) -> &mut Vec<ArrayRef> {
175        self.0.physical_mut().chunks_mut()
176    }
177
178    fn shrink_to_fit(&mut self) {
179        self.0.physical_mut().shrink_to_fit()
180    }
181
182    fn slice(&self, offset: i64, length: usize) -> Series {
183        self.0.slice(offset, length).into_series()
184    }
185    fn split_at(&self, offset: i64) -> (Series, Series) {
186        let (a, b) = self.0.split_at(offset);
187        (a.into_series(), b.into_series())
188    }
189
190    fn _sum_as_f64(&self) -> f64 {
191        self.0.physical()._sum_as_f64()
192    }
193
194    fn mean(&self) -> Option<f64> {
195        self.0.physical().mean()
196    }
197
198    fn median(&self) -> Option<f64> {
199        self.0.physical().median()
200    }
201
202    fn append(&mut self, other: &Series) -> PolarsResult<()> {
203        polars_ensure!(self.0.dtype() == other.dtype(), append);
204        let mut other = other.to_physical_repr().into_owned();
205        self.0
206            .physical_mut()
207            .append_owned(std::mem::take(other._get_inner_mut().as_mut()))
208    }
209    fn append_owned(&mut self, mut other: Series) -> PolarsResult<()> {
210        polars_ensure!(self.0.dtype() == other.dtype(), append);
211        self.0.physical_mut().append_owned(std::mem::take(
212            &mut other
213                ._get_inner_mut()
214                .as_any_mut()
215                .downcast_mut::<DatetimeChunked>()
216                .unwrap()
217                .phys,
218        ))
219    }
220
221    fn extend(&mut self, other: &Series) -> PolarsResult<()> {
222        polars_ensure!(self.0.dtype() == other.dtype(), extend);
223        let other = other.to_physical_repr();
224        self.0
225            .physical_mut()
226            .extend(other.as_ref().as_ref().as_ref())?;
227        Ok(())
228    }
229
230    fn filter(&self, filter: &BooleanChunked) -> PolarsResult<Series> {
231        self.0.physical().filter(filter).map(|ca| {
232            ca.into_datetime(self.0.time_unit(), self.0.time_zone().clone())
233                .into_series()
234        })
235    }
236
237    fn take(&self, indices: &IdxCa) -> PolarsResult<Series> {
238        let ca = self.0.physical().take(indices)?;
239        Ok(ca
240            .into_datetime(self.0.time_unit(), self.0.time_zone().clone())
241            .into_series())
242    }
243
244    unsafe fn take_unchecked(&self, indices: &IdxCa) -> Series {
245        let ca = self.0.physical().take_unchecked(indices);
246        ca.into_datetime(self.0.time_unit(), self.0.time_zone().clone())
247            .into_series()
248    }
249
250    fn take_slice(&self, indices: &[IdxSize]) -> PolarsResult<Series> {
251        let ca = self.0.physical().take(indices)?;
252        Ok(ca
253            .into_datetime(self.0.time_unit(), self.0.time_zone().clone())
254            .into_series())
255    }
256
257    unsafe fn take_slice_unchecked(&self, indices: &[IdxSize]) -> Series {
258        let ca = self.0.physical().take_unchecked(indices);
259        ca.into_datetime(self.0.time_unit(), self.0.time_zone().clone())
260            .into_series()
261    }
262
263    fn len(&self) -> usize {
264        self.0.len()
265    }
266
267    fn rechunk(&self) -> Series {
268        self.0
269            .physical()
270            .rechunk()
271            .into_owned()
272            .into_datetime(self.0.time_unit(), self.0.time_zone().clone())
273            .into_series()
274    }
275
276    fn new_from_index(&self, index: usize, length: usize) -> Series {
277        self.0
278            .physical()
279            .new_from_index(index, length)
280            .into_datetime(self.0.time_unit(), self.0.time_zone().clone())
281            .into_series()
282    }
283
284    fn cast(&self, dtype: &DataType, cast_options: CastOptions) -> PolarsResult<Series> {
285        match dtype {
286            DataType::String => Ok(self.0.to_string("iso")?.into_series()),
287            _ => self.0.cast_with_options(dtype, cast_options),
288        }
289    }
290
291    #[inline]
292    unsafe fn get_unchecked(&self, index: usize) -> AnyValue<'_> {
293        self.0.get_any_value_unchecked(index)
294    }
295
296    fn sort_with(&self, options: SortOptions) -> PolarsResult<Series> {
297        Ok(self
298            .0
299            .physical()
300            .sort_with(options)
301            .into_datetime(self.0.time_unit(), self.0.time_zone().clone())
302            .into_series())
303    }
304
305    fn arg_sort(&self, options: SortOptions) -> IdxCa {
306        self.0.physical().arg_sort(options)
307    }
308
309    fn null_count(&self) -> usize {
310        self.0.null_count()
311    }
312
313    fn has_nulls(&self) -> bool {
314        self.0.has_nulls()
315    }
316
317    #[cfg(feature = "algorithm_group_by")]
318    fn unique(&self) -> PolarsResult<Series> {
319        self.0.physical().unique().map(|ca| {
320            ca.into_datetime(self.0.time_unit(), self.0.time_zone().clone())
321                .into_series()
322        })
323    }
324
325    #[cfg(feature = "algorithm_group_by")]
326    fn n_unique(&self) -> PolarsResult<usize> {
327        self.0.physical().n_unique()
328    }
329
330    #[cfg(feature = "algorithm_group_by")]
331    fn arg_unique(&self) -> PolarsResult<IdxCa> {
332        self.0.physical().arg_unique()
333    }
334
335    fn is_null(&self) -> BooleanChunked {
336        self.0.is_null()
337    }
338
339    fn is_not_null(&self) -> BooleanChunked {
340        self.0.is_not_null()
341    }
342
343    fn reverse(&self) -> Series {
344        self.0
345            .physical()
346            .reverse()
347            .into_datetime(self.0.time_unit(), self.0.time_zone().clone())
348            .into_series()
349    }
350
351    fn as_single_ptr(&mut self) -> PolarsResult<usize> {
352        self.0.physical_mut().as_single_ptr()
353    }
354
355    fn shift(&self, periods: i64) -> Series {
356        self.0
357            .physical()
358            .shift(periods)
359            .into_datetime(self.0.time_unit(), self.0.time_zone().clone())
360            .into_series()
361    }
362
363    fn max_reduce(&self) -> PolarsResult<Scalar> {
364        let sc = self.0.physical().max_reduce();
365
366        Ok(Scalar::new(self.dtype().clone(), sc.value().clone()))
367    }
368
369    fn min_reduce(&self) -> PolarsResult<Scalar> {
370        let sc = self.0.physical().min_reduce();
371
372        Ok(Scalar::new(self.dtype().clone(), sc.value().clone()))
373    }
374
375    fn median_reduce(&self) -> PolarsResult<Scalar> {
376        let av: AnyValue = self.median().map(|v| v as i64).into();
377        Ok(Scalar::new(self.dtype().clone(), av))
378    }
379
380    fn quantile_reduce(&self, _quantile: f64, _method: QuantileMethod) -> PolarsResult<Scalar> {
381        Ok(Scalar::new(self.dtype().clone(), AnyValue::Null))
382    }
383
384    fn clone_inner(&self) -> Arc<dyn SeriesTrait> {
385        Arc::new(SeriesWrap(Clone::clone(&self.0)))
386    }
387
388    fn find_validity_mismatch(&self, other: &Series, idxs: &mut Vec<IdxSize>) {
389        self.0.physical().find_validity_mismatch(other, idxs)
390    }
391
392    fn as_any(&self) -> &dyn Any {
393        &self.0
394    }
395
396    fn as_any_mut(&mut self) -> &mut dyn Any {
397        &mut self.0
398    }
399
400    fn as_phys_any(&self) -> &dyn Any {
401        self.0.physical()
402    }
403
404    fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
405        self as _
406    }
407}