Path: blob/main/crates/polars-ops/src/series/ops/duration.rs
8449 views
use arrow::temporal_conversions::{MICROSECONDS, MILLISECONDS, NANOSECONDS, SECONDS_IN_DAY};1use polars_core::datatypes::{AnyValue, DataType, TimeUnit};2use polars_core::prelude::Column;3use polars_error::PolarsResult;45pub fn impl_duration(s: &[Column], time_unit: TimeUnit) -> PolarsResult<Column> {6if s.iter().any(|s| s.is_empty()) {7return Ok(Column::new_empty(8s[0].name().clone(),9&DataType::Duration(time_unit),10));11}1213// TODO: Handle overflow for UInt6414let weeks = &s[0];15let days = &s[1];16let hours = &s[2];17let minutes = &s[3];18let seconds = &s[4];19let mut milliseconds = s[5].clone();20let mut microseconds = s[6].clone();21let mut nanoseconds = s[7].clone();2223let is_scalar = |s: &Column| s.len() == 1;24let is_zero = |av: AnyValue<'_>| match av {25v if v.is_integer() => v == AnyValue::Int64(0),26v if v.is_float() => v == AnyValue::Float64(0.0),27_ => false,28};29let is_zero_scalar = |s: &Column| is_scalar(s) && is_zero(s.get(0).unwrap());3031// Process subseconds32let max_len = s.iter().map(|s| s.len()).max().unwrap();33let mut duration = match time_unit {34TimeUnit::Microseconds => {35if is_scalar(µseconds) {36microseconds = microseconds.new_from_index(0, max_len);37}38if !is_zero_scalar(&nanoseconds) {39microseconds = (microseconds + (nanoseconds.wrapping_trunc_div_scalar(1_000)))?;40}41if !is_zero_scalar(&milliseconds) {42microseconds = (microseconds + milliseconds * 1_000)?;43}44microseconds45},46TimeUnit::Nanoseconds => {47if is_scalar(&nanoseconds) {48nanoseconds = nanoseconds.new_from_index(0, max_len);49}50if !is_zero_scalar(µseconds) {51nanoseconds = (nanoseconds + microseconds * 1_000)?;52}53if !is_zero_scalar(&milliseconds) {54nanoseconds = (nanoseconds + milliseconds * 1_000_000)?;55}56nanoseconds57},58TimeUnit::Milliseconds => {59if is_scalar(&milliseconds) {60milliseconds = milliseconds.new_from_index(0, max_len);61}62if !is_zero_scalar(&nanoseconds) {63milliseconds = (milliseconds + (nanoseconds.wrapping_trunc_div_scalar(1_000_000)))?;64}65if !is_zero_scalar(µseconds) {66milliseconds = (milliseconds + (microseconds.wrapping_trunc_div_scalar(1_000)))?;67}68milliseconds69},70};7172// Process other duration specifiers73let multiplier = match time_unit {74TimeUnit::Nanoseconds => NANOSECONDS,75TimeUnit::Microseconds => MICROSECONDS,76TimeUnit::Milliseconds => MILLISECONDS,77};78if !is_zero_scalar(seconds) {79duration = (duration + seconds * multiplier)?;80}81if !is_zero_scalar(minutes) {82duration = (duration + minutes * (multiplier * 60))?;83}84if !is_zero_scalar(hours) {85duration = (duration + hours * (multiplier * 60 * 60))?;86}87if !is_zero_scalar(days) {88duration = (duration + days * (multiplier * SECONDS_IN_DAY))?;89}90if !is_zero_scalar(weeks) {91duration = (duration + weeks * (multiplier * SECONDS_IN_DAY * 7))?;92}9394duration.cast(&DataType::Duration(time_unit))95}969798