Path: blob/main/crates/polars-expr/src/dispatch/range/datetime_range.rs
7884 views
#[cfg(feature = "timezones")]1use polars_core::prelude::time_zone::parse_time_zone;2use polars_core::prelude::*;3#[cfg(feature = "dtype-date")]4use polars_plan::dsl::DateRangeArgs;5use polars_time::{ClosedWindow, Duration, datetime_range_impl};67use super::utils::{8ensure_items_contain_exactly_one_value, temporal_ranges_impl_broadcast,9temporal_series_to_i64_scalar,10};1112const CAPACITY_FACTOR: usize = 5;1314#[cfg(feature = "dtype-date")]15pub(super) fn date_range(16s: &[Column],17interval: Option<Duration>,18closed: ClosedWindow,19arg_type: DateRangeArgs,20) -> PolarsResult<Column> {21let dt_type = DataType::Datetime(TimeUnit::Microseconds, None);22match arg_type {23DateRangeArgs::StartEndInterval => dt_range_start_end_interval(24&s[0].cast(&dt_type)?,25&s[1].cast(&dt_type)?,26interval.unwrap(),27closed,28),29DateRangeArgs::StartEndSamples => todo!(),30DateRangeArgs::StartIntervalSamples => todo!(),31DateRangeArgs::EndIntervalSamples => todo!(),32}33.map(|c| c.cast(&DataType::Date))?34}3536#[cfg(feature = "dtype-date")]37pub(super) fn date_ranges(38s: &[Column],39interval: Option<Duration>,40closed: ClosedWindow,41arg_type: DateRangeArgs,42) -> PolarsResult<Column> {43let dt_type = DataType::Datetime(TimeUnit::Microseconds, None);44match arg_type {45DateRangeArgs::StartEndInterval => dt_ranges_start_end_interval(46&s[0].cast(&dt_type)?,47&s[1].cast(&dt_type)?,48interval.unwrap(),49closed,50),51DateRangeArgs::StartEndSamples => todo!(),52DateRangeArgs::StartIntervalSamples => todo!(),53DateRangeArgs::EndIntervalSamples => todo!(),54}55.map(|c| c.cast(&DataType::List(Box::new(DataType::Date))))?56}5758#[cfg(feature = "dtype-datetime")]59pub(super) fn datetime_range(60s: &[Column],61interval: Option<Duration>,62closed: ClosedWindow,63arg_type: DateRangeArgs,64) -> PolarsResult<Column> {65match arg_type {66DateRangeArgs::StartEndInterval => {67dt_range_start_end_interval(&s[0], &s[1], interval.unwrap(), closed)68},69DateRangeArgs::StartEndSamples => todo!(),70DateRangeArgs::StartIntervalSamples => todo!(),71DateRangeArgs::EndIntervalSamples => todo!(),72}73}7475#[cfg(feature = "dtype-datetime")]76pub(super) fn datetime_ranges(77s: &[Column],78interval: Option<Duration>,79closed: ClosedWindow,80arg_type: DateRangeArgs,81) -> PolarsResult<Column> {82match arg_type {83DateRangeArgs::StartEndInterval => {84dt_ranges_start_end_interval(&s[0], &s[1], interval.unwrap(), closed)85},86DateRangeArgs::StartEndSamples => todo!(),87DateRangeArgs::StartIntervalSamples => todo!(),88DateRangeArgs::EndIntervalSamples => todo!(),89}90}9192/// Datetime range given start, end, and interval.93fn dt_range_start_end_interval(94start: &Column,95end: &Column,96interval: Duration,97closed: ClosedWindow,98) -> PolarsResult<Column> {99ensure_items_contain_exactly_one_value(&[start, end], &["start", "end"])?;100let dtype = start.dtype();101102if let DataType::Datetime(tu, time_zone) = dtype {103let tz = match time_zone {104#[cfg(feature = "timezones")]105Some(tz) => Some(parse_time_zone(tz)?),106_ => None,107};108let name = start.name();109let start = temporal_series_to_i64_scalar(start)110.ok_or_else(|| polars_err!(ComputeError: "start is an out-of-range time."))?;111let end = temporal_series_to_i64_scalar(end)112.ok_or_else(|| polars_err!(ComputeError: "end is an out-of-range time."))?;113let result =114datetime_range_impl(name.clone(), start, end, interval, closed, *tu, tz.as_ref())?;115Ok(result.into_column())116} else {117polars_bail!(ComputeError: "expected Datetime input, got {:?}", dtype);118}119}120121fn dt_ranges_start_end_interval(122start: &Column,123end: &Column,124interval: Duration,125closed: ClosedWindow,126) -> PolarsResult<Column> {127let dtype = start.dtype();128129let start = start.to_physical_repr();130let start = start.i64()?;131let end = end.to_physical_repr();132let end = end.i64()?;133134let out = if let DataType::Datetime(tu, time_zone) = dtype {135let mut builder = ListPrimitiveChunkedBuilder::<Int64Type>::new(136start.name().clone(),137start.len(),138start.len() * CAPACITY_FACTOR,139DataType::Int64,140);141142let tz = match time_zone {143#[cfg(feature = "timezones")]144Some(tz) => Some(parse_time_zone(tz)?),145_ => None,146};147let range_impl = |start, end, builder: &mut ListPrimitiveChunkedBuilder<Int64Type>| {148let rng = datetime_range_impl(149PlSmallStr::EMPTY,150start,151end,152interval,153closed,154*tu,155tz.as_ref(),156)?;157builder.append_slice(rng.physical().cont_slice().unwrap());158Ok(())159};160161temporal_ranges_impl_broadcast(start, end, range_impl, &mut builder)?162} else {163polars_bail!(ComputeError: "expected Datetime input, got {:?}", dtype);164};165166let to_type = DataType::List(Box::new(dtype.clone()));167out.cast(&to_type)168}169170171