Path: blob/main/crates/polars-plan/src/plans/aexpr/function_expr/datetime.rs
7889 views
use super::*;12#[cfg_attr(feature = "ir_serde", derive(serde::Serialize, serde::Deserialize))]3#[derive(Clone, PartialEq, Debug, Eq, Hash)]4pub enum IRTemporalFunction {5Millennium,6Century,7Year,8IsLeapYear,9IsoYear,10Quarter,11Month,12DaysInMonth,13Week,14WeekDay,15Day,16OrdinalDay,17Time,18Date,19Datetime,20#[cfg(feature = "dtype-duration")]21Duration(TimeUnit),22Hour,23Minute,24Second,25Millisecond,26Microsecond,27Nanosecond,28#[cfg(feature = "dtype-duration")]29TotalDays {30fractional: bool,31},32#[cfg(feature = "dtype-duration")]33TotalHours {34fractional: bool,35},36#[cfg(feature = "dtype-duration")]37TotalMinutes {38fractional: bool,39},40#[cfg(feature = "dtype-duration")]41TotalSeconds {42fractional: bool,43},44#[cfg(feature = "dtype-duration")]45TotalMilliseconds {46fractional: bool,47},48#[cfg(feature = "dtype-duration")]49TotalMicroseconds {50fractional: bool,51},52#[cfg(feature = "dtype-duration")]53TotalNanoseconds {54fractional: bool,55},56ToString(String),57CastTimeUnit(TimeUnit),58WithTimeUnit(TimeUnit),59#[cfg(feature = "timezones")]60ConvertTimeZone(TimeZone),61TimeStamp(TimeUnit),62Truncate,63#[cfg(feature = "offset_by")]64OffsetBy,65#[cfg(feature = "month_start")]66MonthStart,67#[cfg(feature = "month_end")]68MonthEnd,69#[cfg(feature = "timezones")]70BaseUtcOffset,71#[cfg(feature = "timezones")]72DSTOffset,73Round,74Replace,75#[cfg(feature = "timezones")]76ReplaceTimeZone(Option<TimeZone>, NonExistent),77Combine(TimeUnit),78DatetimeFunction {79time_unit: TimeUnit,80time_zone: Option<TimeZone>,81},82}8384impl IRTemporalFunction {85pub(super) fn get_field(&self, mapper: FieldsMapper) -> PolarsResult<Field> {86use IRTemporalFunction::*;87match self {88Millennium | Century | Year | IsoYear => mapper.with_dtype(DataType::Int32),89OrdinalDay => mapper.with_dtype(DataType::Int16),90Month | DaysInMonth | Quarter | Week | WeekDay | Day | Hour | Minute | Second => {91mapper.with_dtype(DataType::Int8)92},93Millisecond | Microsecond | Nanosecond => mapper.with_dtype(DataType::Int32),94#[cfg(feature = "dtype-duration")]95TotalDays { fractional }96| TotalHours { fractional }97| TotalMinutes { fractional }98| TotalSeconds { fractional }99| TotalMilliseconds { fractional }100| TotalMicroseconds { fractional }101| TotalNanoseconds { fractional } => {102if *fractional {103mapper.with_dtype(DataType::Float64)104} else {105mapper.with_dtype(DataType::Int64)106}107},108ToString(_) => mapper.with_dtype(DataType::String),109WithTimeUnit(tu) | CastTimeUnit(tu) => mapper.try_map_dtype(|dt| match dt {110DataType::Duration(_) => Ok(DataType::Duration(*tu)),111DataType::Datetime(_, tz) => Ok(DataType::Datetime(*tu, tz.clone())),112dtype => polars_bail!(ComputeError: "expected duration or datetime, got {}", dtype),113}),114#[cfg(feature = "timezones")]115ConvertTimeZone(tz) => mapper.try_map_dtype(|dt| match dt {116DataType::Datetime(tu, _) => Ok(DataType::Datetime(*tu, Some(tz.clone()))),117dtype => polars_bail!(ComputeError: "expected Datetime, got {}", dtype),118}),119TimeStamp(_) => mapper.with_dtype(DataType::Int64),120IsLeapYear => mapper.with_dtype(DataType::Boolean),121Time => mapper.with_dtype(DataType::Time),122#[cfg(feature = "dtype-duration")]123Duration(tu) => mapper.with_dtype(DataType::Duration(*tu)),124Date => mapper.with_dtype(DataType::Date),125Datetime => mapper.try_map_dtype(|dt| match dt {126DataType::Datetime(tu, _) => Ok(DataType::Datetime(*tu, None)),127dtype => polars_bail!(ComputeError: "expected Datetime, got {}", dtype),128}),129Truncate => mapper.with_same_dtype(),130#[cfg(feature = "offset_by")]131OffsetBy => mapper.with_same_dtype(),132#[cfg(feature = "month_start")]133MonthStart => mapper.with_same_dtype(),134#[cfg(feature = "month_end")]135MonthEnd => mapper.with_same_dtype(),136#[cfg(feature = "timezones")]137BaseUtcOffset => mapper.with_dtype(DataType::Duration(TimeUnit::Milliseconds)),138#[cfg(feature = "timezones")]139DSTOffset => mapper.with_dtype(DataType::Duration(TimeUnit::Milliseconds)),140Round => mapper.with_same_dtype(),141Replace => mapper.with_same_dtype(),142#[cfg(feature = "timezones")]143ReplaceTimeZone(tz, _non_existent) => mapper.map_datetime_dtype_timezone(tz.as_ref()),144DatetimeFunction {145time_unit,146time_zone,147} => Ok(Field::new(148PlSmallStr::from_static("datetime"),149DataType::Datetime(*time_unit, time_zone.clone()),150)),151Combine(tu) => mapper.try_map_dtype(|dt| match dt {152DataType::Datetime(_, tz) => Ok(DataType::Datetime(*tu, tz.clone())),153DataType::Date => Ok(DataType::Datetime(*tu, None)),154dtype => {155polars_bail!(ComputeError: "expected Date or Datetime, got {}", dtype)156},157}),158}159}160161pub fn function_options(&self) -> FunctionOptions {162use IRTemporalFunction as T;163match self {164T::Millennium165| T::Century166| T::Year167| T::IsLeapYear168| T::IsoYear169| T::Quarter170| T::Month171| T::DaysInMonth172| T::Week173| T::WeekDay174| T::Day175| T::OrdinalDay176| T::Time177| T::Date178| T::Datetime179| T::Hour180| T::Minute181| T::Second182| T::Millisecond183| T::Microsecond184| T::Nanosecond185| T::ToString(_)186| T::TimeStamp(_)187| T::CastTimeUnit(_)188| T::WithTimeUnit(_) => FunctionOptions::elementwise(),189#[cfg(feature = "dtype-duration")]190T::TotalDays { .. }191| T::TotalHours { .. }192| T::TotalMinutes { .. }193| T::TotalSeconds { .. }194| T::TotalMilliseconds { .. }195| T::TotalMicroseconds { .. }196| T::TotalNanoseconds { .. } => FunctionOptions::elementwise(),197#[cfg(feature = "timezones")]198T::ConvertTimeZone(_) => FunctionOptions::elementwise(),199#[cfg(feature = "month_start")]200T::MonthStart => FunctionOptions::elementwise(),201#[cfg(feature = "month_end")]202T::MonthEnd => FunctionOptions::elementwise(),203#[cfg(feature = "timezones")]204T::BaseUtcOffset | T::DSTOffset => FunctionOptions::elementwise(),205T::Truncate => FunctionOptions::elementwise(),206#[cfg(feature = "offset_by")]207T::OffsetBy => FunctionOptions::elementwise(),208T::Round => FunctionOptions::elementwise(),209T::Replace => FunctionOptions::elementwise(),210#[cfg(feature = "dtype-duration")]211T::Duration(_) => FunctionOptions::elementwise(),212#[cfg(feature = "timezones")]213T::ReplaceTimeZone(_, _) => FunctionOptions::elementwise(),214T::Combine(_) => FunctionOptions::elementwise(),215T::DatetimeFunction { .. } => {216FunctionOptions::elementwise().with_flags(|f| f | FunctionFlags::ALLOW_RENAME)217},218}219}220}221222impl Display for IRTemporalFunction {223fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {224use IRTemporalFunction::*;225let s = match self {226Millennium => "millennium",227Century => "century",228Year => "year",229IsLeapYear => "is_leap_year",230IsoYear => "iso_year",231Quarter => "quarter",232Month => "month",233DaysInMonth => "days_in_month",234Week => "week",235WeekDay => "weekday",236Day => "day",237OrdinalDay => "ordinal_day",238Time => "time",239Date => "date",240Datetime => "datetime",241#[cfg(feature = "dtype-duration")]242Duration(_) => "duration",243Hour => "hour",244Minute => "minute",245Second => "second",246Millisecond => "millisecond",247Microsecond => "microsecond",248Nanosecond => "nanosecond",249#[cfg(feature = "dtype-duration")]250TotalDays { .. } => "total_days",251#[cfg(feature = "dtype-duration")]252TotalHours { .. } => "total_hours",253#[cfg(feature = "dtype-duration")]254TotalMinutes { .. } => "total_minutes",255#[cfg(feature = "dtype-duration")]256TotalSeconds { .. } => "total_seconds",257#[cfg(feature = "dtype-duration")]258TotalMilliseconds { .. } => "total_milliseconds",259#[cfg(feature = "dtype-duration")]260TotalMicroseconds { .. } => "total_microseconds",261#[cfg(feature = "dtype-duration")]262TotalNanoseconds { .. } => "total_nanoseconds",263ToString(_) => "to_string",264#[cfg(feature = "timezones")]265ConvertTimeZone(_) => "convert_time_zone",266CastTimeUnit(_) => "cast_time_unit",267WithTimeUnit(_) => "with_time_unit",268TimeStamp(tu) => return write!(f, "dt.timestamp({tu})"),269Truncate => "truncate",270#[cfg(feature = "offset_by")]271OffsetBy => "offset_by",272#[cfg(feature = "month_start")]273MonthStart => "month_start",274#[cfg(feature = "month_end")]275MonthEnd => "month_end",276#[cfg(feature = "timezones")]277BaseUtcOffset => "base_utc_offset",278#[cfg(feature = "timezones")]279DSTOffset => "dst_offset",280Round => "round",281Replace => "replace",282#[cfg(feature = "timezones")]283ReplaceTimeZone(_, _) => "replace_time_zone",284DatetimeFunction { .. } => return write!(f, "dt.datetime"),285Combine(_) => "combine",286};287write!(f, "dt.{s}")288}289}290291292