Path: blob/main/crates/polars-core/src/series/implementations/date.rs
8421 views
//! This module exists to reduce compilation times.1//!2//! All the data types are backed by a physical type in memory e.g. Date -> i32, Datetime-> i64.3//!4//! Series lead to code implementations of all traits. Whereas there are a lot of duplicates due to5//! data types being backed by the same physical type. In this module we reduce compile times by6//! opting for a little more run time cost. We cast to the physical type -> apply the operation and7//! (depending on the result) cast back to the original type8//!9use super::*;10#[cfg(feature = "algorithm_group_by")]11use crate::frame::group_by::*;12use crate::prelude::*;1314unsafe impl IntoSeries for DateChunked {15fn into_series(self) -> Series {16Series(Arc::new(SeriesWrap(self)))17}18}1920impl private::PrivateSeries for SeriesWrap<DateChunked> {21fn compute_len(&mut self) {22self.0.physical_mut().compute_len()23}2425fn _field(&self) -> Cow<'_, Field> {26Cow::Owned(self.0.field())27}2829fn _dtype(&self) -> &DataType {30self.0.dtype()31}3233fn _get_flags(&self) -> StatisticsFlags {34self.0.physical().get_flags()35}3637fn _set_flags(&mut self, flags: StatisticsFlags) {38self.0.physical_mut().set_flags(flags)39}4041#[cfg(feature = "zip_with")]42fn zip_with_same_type(&self, mask: &BooleanChunked, other: &Series) -> PolarsResult<Series> {43let other = other.to_physical_repr().into_owned();44self.045.physical()46.zip_with(mask, other.as_ref().as_ref())47.map(|ca| ca.into_date().into_series())48}4950fn into_total_eq_inner<'a>(&'a self) -> Box<dyn TotalEqInner + 'a> {51self.0.physical().into_total_eq_inner()52}5354fn into_total_ord_inner<'a>(&'a self) -> Box<dyn TotalOrdInner + 'a> {55self.0.physical().into_total_ord_inner()56}5758fn vec_hash(59&self,60random_state: PlSeedableRandomStateQuality,61buf: &mut Vec<u64>,62) -> PolarsResult<()> {63self.0.physical().vec_hash(random_state, buf)?;64Ok(())65}6667fn vec_hash_combine(68&self,69build_hasher: PlSeedableRandomStateQuality,70hashes: &mut [u64],71) -> PolarsResult<()> {72self.0.physical().vec_hash_combine(build_hasher, hashes)?;73Ok(())74}7576#[cfg(feature = "algorithm_group_by")]77unsafe fn agg_min(&self, groups: &GroupsType) -> Series {78self.0.physical().agg_min(groups).into_date().into_series()79}8081#[cfg(feature = "algorithm_group_by")]82unsafe fn agg_max(&self, groups: &GroupsType) -> Series {83self.0.physical().agg_max(groups).into_date().into_series()84}8586#[cfg(feature = "algorithm_group_by")]87unsafe fn agg_arg_min(&self, groups: &GroupsType) -> Series {88self.0.physical().agg_arg_min(groups)89}9091#[cfg(feature = "algorithm_group_by")]92unsafe fn agg_arg_max(&self, groups: &GroupsType) -> Series {93self.0.physical().agg_arg_max(groups)94}9596#[cfg(feature = "algorithm_group_by")]97unsafe fn agg_list(&self, groups: &GroupsType) -> Series {98// we cannot cast and dispatch as the inner type of the list would be incorrect99self.0100.physical()101.agg_list(groups)102.cast(&DataType::List(Box::new(self.dtype().clone())))103.unwrap()104}105106fn subtract(&self, rhs: &Series) -> PolarsResult<Series> {107match rhs.dtype() {108DataType::Date => {109let dt = DataType::Datetime(TimeUnit::Microseconds, None);110let lhs = self.cast(&dt, CastOptions::NonStrict)?;111let rhs = rhs.cast(&dt)?;112lhs.subtract(&rhs)113},114DataType::Duration(_) => std::ops::Sub::sub(115&self.cast(116&DataType::Datetime(TimeUnit::Microseconds, None),117CastOptions::NonStrict,118)?,119rhs,120)?121.cast(&DataType::Date),122dtr => polars_bail!(opq = sub, DataType::Date, dtr),123}124}125126fn add_to(&self, rhs: &Series) -> PolarsResult<Series> {127match rhs.dtype() {128DataType::Duration(_) => std::ops::Add::add(129&self.cast(130&DataType::Datetime(TimeUnit::Microseconds, None),131CastOptions::NonStrict,132)?,133rhs,134)?135.cast(&DataType::Date),136dtr => polars_bail!(opq = add, DataType::Date, dtr),137}138}139140fn multiply(&self, rhs: &Series) -> PolarsResult<Series> {141polars_bail!(opq = mul, self.0.dtype(), rhs.dtype());142}143144fn divide(&self, rhs: &Series) -> PolarsResult<Series> {145polars_bail!(opq = div, self.0.dtype(), rhs.dtype());146}147148fn remainder(&self, rhs: &Series) -> PolarsResult<Series> {149polars_bail!(opq = rem, self.0.dtype(), rhs.dtype());150}151#[cfg(feature = "algorithm_group_by")]152fn group_tuples(&self, multithreaded: bool, sorted: bool) -> PolarsResult<GroupsType> {153self.0.physical().group_tuples(multithreaded, sorted)154}155156fn arg_sort_multiple(157&self,158by: &[Column],159options: &SortMultipleOptions,160) -> PolarsResult<IdxCa> {161self.0.physical().arg_sort_multiple(by, options)162}163}164165impl SeriesTrait for SeriesWrap<DateChunked> {166fn rename(&mut self, name: PlSmallStr) {167self.0.rename(name);168}169170fn chunk_lengths(&self) -> ChunkLenIter<'_> {171self.0.physical().chunk_lengths()172}173174fn name(&self) -> &PlSmallStr {175self.0.name()176}177178fn chunks(&self) -> &Vec<ArrayRef> {179self.0.physical().chunks()180}181182unsafe fn chunks_mut(&mut self) -> &mut Vec<ArrayRef> {183self.0.physical_mut().chunks_mut()184}185186fn shrink_to_fit(&mut self) {187self.0.physical_mut().shrink_to_fit()188}189190fn slice(&self, offset: i64, length: usize) -> Series {191self.0.slice(offset, length).into_series()192}193194fn split_at(&self, offset: i64) -> (Series, Series) {195let (a, b) = self.0.split_at(offset);196(a.into_series(), b.into_series())197}198199fn _sum_as_f64(&self) -> f64 {200self.0.physical()._sum_as_f64()201}202203fn mean(&self) -> Option<f64> {204self.0.physical().mean()205}206207fn median(&self) -> Option<f64> {208self.0.physical().median()209}210211fn append(&mut self, other: &Series) -> PolarsResult<()> {212polars_ensure!(self.0.dtype() == other.dtype(), append);213let mut other = other.to_physical_repr().into_owned();214self.0215.physical_mut()216.append_owned(std::mem::take(other._get_inner_mut().as_mut()))217}218219fn append_owned(&mut self, mut other: Series) -> PolarsResult<()> {220polars_ensure!(self.0.dtype() == other.dtype(), append);221self.0.physical_mut().append_owned(std::mem::take(222&mut other223._get_inner_mut()224.as_any_mut()225.downcast_mut::<DateChunked>()226.unwrap()227.phys,228))229}230231fn extend(&mut self, other: &Series) -> PolarsResult<()> {232polars_ensure!(self.0.dtype() == other.dtype(), extend);233// 3 refs234// ref Cow235// ref SeriesTrait236// ref ChunkedArray237let other = other.to_physical_repr();238self.0239.physical_mut()240.extend(other.as_ref().as_ref().as_ref())?;241Ok(())242}243244fn filter(&self, filter: &BooleanChunked) -> PolarsResult<Series> {245self.0246.physical()247.filter(filter)248.map(|ca| ca.into_date().into_series())249}250251fn take(&self, indices: &IdxCa) -> PolarsResult<Series> {252Ok(self.0.physical().take(indices)?.into_date().into_series())253}254255unsafe fn take_unchecked(&self, indices: &IdxCa) -> Series {256self.0257.physical()258.take_unchecked(indices)259.into_date()260.into_series()261}262263fn take_slice(&self, indices: &[IdxSize]) -> PolarsResult<Series> {264Ok(self.0.physical().take(indices)?.into_date().into_series())265}266267unsafe fn take_slice_unchecked(&self, indices: &[IdxSize]) -> Series {268self.0269.physical()270.take_unchecked(indices)271.into_date()272.into_series()273}274275fn deposit(&self, validity: &Bitmap) -> Series {276self.0277.physical()278.deposit(validity)279.into_date()280.into_series()281}282283fn len(&self) -> usize {284self.0.len()285}286287fn rechunk(&self) -> Series {288self.0289.physical()290.rechunk()291.into_owned()292.into_date()293.into_series()294}295296fn new_from_index(&self, index: usize, length: usize) -> Series {297self.0298.physical()299.new_from_index(index, length)300.into_date()301.into_series()302}303304fn cast(&self, dtype: &DataType, cast_options: CastOptions) -> PolarsResult<Series> {305match dtype {306DataType::String => Ok(self307.0308.clone()309.into_series()310.date()311.unwrap()312.to_string("%Y-%m-%d")?313.into_series()),314#[cfg(feature = "dtype-datetime")]315DataType::Datetime(_, _) => {316let mut out = self.0.cast_with_options(dtype, CastOptions::NonStrict)?;317out.set_sorted_flag(self.0.physical().is_sorted_flag());318Ok(out)319},320_ => self.0.cast_with_options(dtype, cast_options),321}322}323324#[inline]325unsafe fn get_unchecked(&self, index: usize) -> AnyValue<'_> {326self.0.get_any_value_unchecked(index)327}328329fn sort_with(&self, options: SortOptions) -> PolarsResult<Series> {330Ok(self331.0332.physical()333.sort_with(options)334.into_date()335.into_series())336}337338fn arg_sort(&self, options: SortOptions) -> IdxCa {339self.0.physical().arg_sort(options)340}341342fn null_count(&self) -> usize {343self.0.null_count()344}345346fn has_nulls(&self) -> bool {347self.0.has_nulls()348}349350#[cfg(feature = "algorithm_group_by")]351fn unique(&self) -> PolarsResult<Series> {352self.0353.physical()354.unique()355.map(|ca| ca.into_date().into_series())356}357358#[cfg(feature = "algorithm_group_by")]359fn n_unique(&self) -> PolarsResult<usize> {360self.0.physical().n_unique()361}362363#[cfg(feature = "algorithm_group_by")]364fn arg_unique(&self) -> PolarsResult<IdxCa> {365self.0.physical().arg_unique()366}367368fn unique_id(&self) -> PolarsResult<(IdxSize, Vec<IdxSize>)> {369ChunkUnique::unique_id(self.0.physical())370}371372fn is_null(&self) -> BooleanChunked {373self.0.is_null()374}375376fn is_not_null(&self) -> BooleanChunked {377self.0.is_not_null()378}379380fn reverse(&self) -> Series {381self.0.physical().reverse().into_date().into_series()382}383384fn as_single_ptr(&mut self) -> PolarsResult<usize> {385self.0.physical_mut().as_single_ptr()386}387388fn shift(&self, periods: i64) -> Series {389self.0.physical().shift(periods).into_date().into_series()390}391392fn max_reduce(&self) -> PolarsResult<Scalar> {393let sc = self.0.physical().max_reduce();394let av = sc.value().as_date();395Ok(Scalar::new(self.dtype().clone(), av))396}397398fn min_reduce(&self) -> PolarsResult<Scalar> {399let sc = self.0.physical().min_reduce();400let av = sc.value().as_date();401Ok(Scalar::new(self.dtype().clone(), av))402}403404#[cfg(feature = "dtype-datetime")]405fn mean_reduce(&self) -> PolarsResult<Scalar> {406let mean = self.mean().map(|v| (v * US_IN_DAY as f64) as i64);407let dtype = DataType::Datetime(TimeUnit::Microseconds, None);408let av = AnyValue::from(mean).as_datetime(TimeUnit::Microseconds, None);409Ok(Scalar::new(dtype, av))410}411412#[cfg(feature = "dtype-datetime")]413fn median_reduce(&self) -> PolarsResult<Scalar> {414let median = self.median().map(|v| (v * (US_IN_DAY as f64)) as i64);415let dtype = DataType::Datetime(TimeUnit::Microseconds, None);416let av = AnyValue::from(median).as_datetime(TimeUnit::Microseconds, None);417Ok(Scalar::new(dtype, av))418}419420#[cfg(feature = "dtype-datetime")]421fn quantile_reduce(&self, quantile: f64, method: QuantileMethod) -> PolarsResult<Scalar> {422let quantile = self.0.physical().quantile_reduce(quantile, method)?;423let v = quantile.value().extract::<f64>().unwrap();424let datetime_us_value = (v * (US_IN_DAY as f64)) as i64;425let av = AnyValue::Datetime(datetime_us_value, TimeUnit::Microseconds, None);426Ok(Scalar::new(427DataType::Datetime(TimeUnit::Microseconds, None),428av,429))430}431432#[cfg(feature = "dtype-datetime")]433fn quantiles_reduce(&self, quantiles: &[f64], method: QuantileMethod) -> PolarsResult<Scalar> {434let result = self.0.physical().quantiles_reduce(quantiles, method)?;435if let AnyValue::List(float_s) = result.value() {436let float_ca = float_s.f64().unwrap();437let int_s = float_ca438.iter()439.map(|v: Option<f64>| v.map(|f| (f * (US_IN_DAY as f64)) as i64))440.collect::<Int64Chunked>()441.into_datetime(TimeUnit::Microseconds, None)442.into_series();443Ok(Scalar::new(444DataType::List(Box::new(DataType::Datetime(TimeUnit::Microseconds, None))),445AnyValue::List(int_s),446))447} else {448polars_bail!(ComputeError: "expected list scalar from quantiles_reduce")449}450}451452#[cfg(feature = "approx_unique")]453fn approx_n_unique(&self) -> PolarsResult<IdxSize> {454Ok(ChunkApproxNUnique::approx_n_unique(self.0.physical()))455}456457fn clone_inner(&self) -> Arc<dyn SeriesTrait> {458Arc::new(SeriesWrap(Clone::clone(&self.0)))459}460461fn find_validity_mismatch(&self, other: &Series, idxs: &mut Vec<IdxSize>) {462self.0.physical().find_validity_mismatch(other, idxs)463}464465fn as_any(&self) -> &dyn Any {466&self.0467}468469fn as_any_mut(&mut self) -> &mut dyn Any {470&mut self.0471}472473fn as_phys_any(&self) -> &dyn Any {474self.0.physical()475}476477fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {478self as _479}480}481482impl private::PrivateSeriesNumeric for SeriesWrap<DateChunked> {483fn bit_repr(&self) -> Option<BitRepr> {484Some(self.0.physical().to_bit_repr())485}486}487488489