This is an automated email from the ASF dual-hosted git repository.

tustvold pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/master by this push:
     new 869e6bc13 add Date32/Date64 support to subtract_dyn (#3974)
869e6bc13 is described below

commit 869e6bc13bdbd503dddfa620a0ae62f3c0145a97
Author: Sinan Gençoğlu <[email protected]>
AuthorDate: Wed Mar 29 15:44:34 2023 +0300

    add Date32/Date64 support to subtract_dyn (#3974)
    
    * add Date32/Date64 support to subtract_dyn
    
    * This commit includes:
        1- add subtract date utilities to types
        2- add test for subtract_dyn function
    
    * fix formatting
---
 arrow-arith/src/arithmetic.rs | 190 ++++++++++++++++++++++++++++++++++++++++++
 arrow-array/src/types.rs      | 102 +++++++++++++++++++++++
 2 files changed, 292 insertions(+)

diff --git a/arrow-arith/src/arithmetic.rs b/arrow-arith/src/arithmetic.rs
index 501878afd..6c0fd497e 100644
--- a/arrow-arith/src/arithmetic.rs
+++ b/arrow-arith/src/arithmetic.rs
@@ -923,6 +923,54 @@ pub fn subtract_dyn(left: &dyn Array, right: &dyn Array) 
-> Result<ArrayRef, Arr
         DataType::Dictionary(_, _) => {
             typed_dict_math_op!(left, right, |a, b| a.sub_wrapping(b), 
math_op_dict)
         }
+        DataType::Date32 => {
+            let l = left.as_primitive::<Date32Type>();
+            match right.data_type() {
+                DataType::Interval(IntervalUnit::YearMonth) => {
+                    let r = right.as_primitive::<IntervalYearMonthType>();
+                    let res = math_op(l, r, Date32Type::subtract_year_months)?;
+                    Ok(Arc::new(res))
+                }
+                DataType::Interval(IntervalUnit::DayTime) => {
+                    let r = right.as_primitive::<IntervalDayTimeType>();
+                    let res = math_op(l, r, Date32Type::subtract_day_time)?;
+                    Ok(Arc::new(res))
+                }
+                DataType::Interval(IntervalUnit::MonthDayNano) => {
+                    let r = right.as_primitive::<IntervalMonthDayNanoType>();
+                    let res = math_op(l, r, 
Date32Type::subtract_month_day_nano)?;
+                    Ok(Arc::new(res))
+                }
+                _ => Err(ArrowError::CastError(format!(
+                    "Cannot perform arithmetic operation between array of type 
{} and array of type {}",
+                    left.data_type(), right.data_type()
+                ))),
+            }
+        }
+        DataType::Date64 => {
+            let l = left.as_primitive::<Date64Type>();
+            match right.data_type() {
+                DataType::Interval(IntervalUnit::YearMonth) => {
+                    let r = right.as_primitive::<IntervalYearMonthType>();
+                    let res = math_op(l, r, Date64Type::subtract_year_months)?;
+                    Ok(Arc::new(res))
+                }
+                DataType::Interval(IntervalUnit::DayTime) => {
+                    let r = right.as_primitive::<IntervalDayTimeType>();
+                    let res = math_op(l, r, Date64Type::subtract_day_time)?;
+                    Ok(Arc::new(res))
+                }
+                DataType::Interval(IntervalUnit::MonthDayNano) => {
+                    let r = right.as_primitive::<IntervalMonthDayNanoType>();
+                    let res = math_op(l, r, 
Date64Type::subtract_month_day_nano)?;
+                    Ok(Arc::new(res))
+                }
+                _ => Err(ArrowError::CastError(format!(
+                    "Cannot perform arithmetic operation between array of type 
{} and array of type {}",
+                    left.data_type(), right.data_type()
+                ))),
+            }
+        }
         _ => {
             downcast_primitive_array!(
                 (left, right) => {
@@ -955,6 +1003,54 @@ pub fn subtract_dyn_checked(
                 math_checked_op_dict
             )
         }
+        DataType::Date32 => {
+            let l = left.as_primitive::<Date32Type>();
+            match right.data_type() {
+                DataType::Interval(IntervalUnit::YearMonth) => {
+                    let r = right.as_primitive::<IntervalYearMonthType>();
+                    let res = math_op(l, r, Date32Type::subtract_year_months)?;
+                    Ok(Arc::new(res))
+                }
+                DataType::Interval(IntervalUnit::DayTime) => {
+                    let r = right.as_primitive::<IntervalDayTimeType>();
+                    let res = math_op(l, r, Date32Type::subtract_day_time)?;
+                    Ok(Arc::new(res))
+                }
+                DataType::Interval(IntervalUnit::MonthDayNano) => {
+                    let r = right.as_primitive::<IntervalMonthDayNanoType>();
+                    let res = math_op(l, r, 
Date32Type::subtract_month_day_nano)?;
+                    Ok(Arc::new(res))
+                }
+                _ => Err(ArrowError::CastError(format!(
+                    "Cannot perform arithmetic operation between array of type 
{} and array of type {}",
+                    left.data_type(), right.data_type()
+                ))),
+            }
+        }
+        DataType::Date64 => {
+            let l = left.as_primitive::<Date64Type>();
+            match right.data_type() {
+                DataType::Interval(IntervalUnit::YearMonth) => {
+                    let r = right.as_primitive::<IntervalYearMonthType>();
+                    let res = math_op(l, r, Date64Type::subtract_year_months)?;
+                    Ok(Arc::new(res))
+                }
+                DataType::Interval(IntervalUnit::DayTime) => {
+                    let r = right.as_primitive::<IntervalDayTimeType>();
+                    let res = math_op(l, r, Date64Type::subtract_day_time)?;
+                    Ok(Arc::new(res))
+                }
+                DataType::Interval(IntervalUnit::MonthDayNano) => {
+                    let r = right.as_primitive::<IntervalMonthDayNanoType>();
+                    let res = math_op(l, r, 
Date64Type::subtract_month_day_nano)?;
+                    Ok(Arc::new(res))
+                }
+                _ => Err(ArrowError::CastError(format!(
+                    "Cannot perform arithmetic operation between array of type 
{} and array of type {}",
+                    left.data_type(), right.data_type()
+                ))),
+            }
+        }
         _ => {
             downcast_primitive_array!(
                 (left, right) => {
@@ -1864,6 +1960,100 @@ mod tests {
         assert_eq!(1, c.value(4));
     }
 
+    #[test]
+    fn test_date32_month_subtract() {
+        let a = Date32Array::from(vec![Date32Type::from_naive_date(
+            NaiveDate::from_ymd_opt(2000, 7, 1).unwrap(),
+        )]);
+        let b =
+            
IntervalYearMonthArray::from(vec![IntervalYearMonthType::make_value(6, 3)]);
+        let c = subtract_dyn(&a, &b).unwrap();
+        let c = c.as_any().downcast_ref::<Date32Array>().unwrap();
+        assert_eq!(
+            c.value(0),
+            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(1994, 4, 
1).unwrap())
+        );
+    }
+
+    #[test]
+    fn test_date32_day_time_subtract() {
+        let a = Date32Array::from(vec![Date32Type::from_naive_date(
+            NaiveDate::from_ymd_opt(2023, 3, 29).unwrap(),
+        )]);
+        let b =
+            IntervalDayTimeArray::from(vec![IntervalDayTimeType::make_value(1, 
86500)]);
+        let c = subtract_dyn(&a, &b).unwrap();
+        let c = c.as_any().downcast_ref::<Date32Array>().unwrap();
+        assert_eq!(
+            c.value(0),
+            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(2023, 3, 
27).unwrap())
+        );
+    }
+
+    #[test]
+    fn test_date32_month_day_nano_subtract() {
+        let a = Date32Array::from(vec![Date32Type::from_naive_date(
+            NaiveDate::from_ymd_opt(2023, 3, 15).unwrap(),
+        )]);
+        let b =
+            
IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
+                1, 2, 0,
+            )]);
+        let c = subtract_dyn(&a, &b).unwrap();
+        let c = c.as_any().downcast_ref::<Date32Array>().unwrap();
+        assert_eq!(
+            c.value(0),
+            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(2023, 2, 
13).unwrap())
+        );
+    }
+
+    #[test]
+    fn test_date64_month_subtract() {
+        let a = Date64Array::from(vec![Date64Type::from_naive_date(
+            NaiveDate::from_ymd_opt(2000, 7, 1).unwrap(),
+        )]);
+        let b =
+            
IntervalYearMonthArray::from(vec![IntervalYearMonthType::make_value(6, 3)]);
+        let c = subtract_dyn(&a, &b).unwrap();
+        let c = c.as_any().downcast_ref::<Date64Array>().unwrap();
+        assert_eq!(
+            c.value(0),
+            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(1994, 4, 
1).unwrap())
+        );
+    }
+
+    #[test]
+    fn test_date64_day_time_subtract() {
+        let a = Date64Array::from(vec![Date64Type::from_naive_date(
+            NaiveDate::from_ymd_opt(2023, 3, 29).unwrap(),
+        )]);
+        let b =
+            IntervalDayTimeArray::from(vec![IntervalDayTimeType::make_value(1, 
86500)]);
+        let c = subtract_dyn(&a, &b).unwrap();
+        let c = c.as_any().downcast_ref::<Date64Array>().unwrap();
+        assert_eq!(
+            c.value(0),
+            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(2023, 3, 
27).unwrap())
+        );
+    }
+
+    #[test]
+    fn test_date64_month_day_nano_subtract() {
+        let a = Date64Array::from(vec![Date64Type::from_naive_date(
+            NaiveDate::from_ymd_opt(2023, 3, 15).unwrap(),
+        )]);
+        let b =
+            
IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
+                1, 2, 0,
+            )]);
+        let c = subtract_dyn(&a, &b).unwrap();
+        let c = c.as_any().downcast_ref::<Date64Array>().unwrap();
+        assert_eq!(
+            c.value(0),
+            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(2023, 2, 
13).unwrap())
+        );
+    }
+
     #[test]
     #[cfg(feature = "dyn_arith_dict")]
     fn test_primitive_array_subtract_dyn_dict() {
diff --git a/arrow-array/src/types.rs b/arrow-array/src/types.rs
index 9f1965b77..60a632a06 100644
--- a/arrow-array/src/types.rs
+++ b/arrow-array/src/types.rs
@@ -511,6 +511,57 @@ impl Date32Type {
         let res = res.add(Duration::nanoseconds(nanos));
         Date32Type::from_naive_date(res)
     }
+
+    /// Subtract the given IntervalYearMonthType to an arrow Date32Type
+    ///
+    /// # Arguments
+    ///
+    /// * `date` - The date on which to perform the operation
+    /// * `delta` - The interval to substract
+    pub fn subtract_year_months(
+        date: <Date32Type as ArrowPrimitiveType>::Native,
+        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
+    ) -> <Date32Type as ArrowPrimitiveType>::Native {
+        let prior = Date32Type::to_naive_date(date);
+        let months = IntervalYearMonthType::to_months(-delta);
+        let posterior = shift_months(prior, months);
+        Date32Type::from_naive_date(posterior)
+    }
+
+    /// Subtract the given IntervalDayTimeType to an arrow Date32Type
+    ///
+    /// # Arguments
+    ///
+    /// * `date` - The date on which to perform the operation
+    /// * `delta` - The interval to subtract
+    pub fn subtract_day_time(
+        date: <Date32Type as ArrowPrimitiveType>::Native,
+        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
+    ) -> <Date32Type as ArrowPrimitiveType>::Native {
+        let (days, ms) = IntervalDayTimeType::to_parts(-delta);
+        let res = Date32Type::to_naive_date(date);
+        let res = res.add(Duration::days(days as i64));
+        let res = res.add(Duration::milliseconds(ms as i64));
+        Date32Type::from_naive_date(res)
+    }
+
+    /// Subtract the given IntervalMonthDayNanoType to an arrow Date32Type
+    ///
+    /// # Arguments
+    ///
+    /// * `date` - The date on which to perform the operation
+    /// * `delta` - The interval to subtract
+    pub fn subtract_month_day_nano(
+        date: <Date32Type as ArrowPrimitiveType>::Native,
+        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
+    ) -> <Date32Type as ArrowPrimitiveType>::Native {
+        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
+        let res = Date32Type::to_naive_date(date);
+        let res = shift_months(res, -months);
+        let res = res.add(Duration::days(-days as i64));
+        let res = res.add(Duration::nanoseconds(-nanos));
+        Date32Type::from_naive_date(res)
+    }
 }
 
 impl Date64Type {
@@ -584,6 +635,57 @@ impl Date64Type {
         let res = res.add(Duration::nanoseconds(nanos));
         Date64Type::from_naive_date(res)
     }
+
+    /// Subtract the given IntervalYearMonthType to an arrow Date64Type
+    ///
+    /// # Arguments
+    ///
+    /// * `date` - The date on which to perform the operation
+    /// * `delta` - The interval to substract
+    pub fn subtract_year_months(
+        date: <Date64Type as ArrowPrimitiveType>::Native,
+        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
+    ) -> <Date64Type as ArrowPrimitiveType>::Native {
+        let prior = Date64Type::to_naive_date(date);
+        let months = IntervalYearMonthType::to_months(-delta);
+        let posterior = shift_months(prior, months);
+        Date64Type::from_naive_date(posterior)
+    }
+
+    /// Subtract the given IntervalDayTimeType to an arrow Date64Type
+    ///
+    /// # Arguments
+    ///
+    /// * `date` - The date on which to perform the operation
+    /// * `delta` - The interval to subtract
+    pub fn subtract_day_time(
+        date: <Date64Type as ArrowPrimitiveType>::Native,
+        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
+    ) -> <Date64Type as ArrowPrimitiveType>::Native {
+        let (days, ms) = IntervalDayTimeType::to_parts(-delta);
+        let res = Date64Type::to_naive_date(date);
+        let res = res.add(Duration::days(days as i64));
+        let res = res.add(Duration::milliseconds(ms as i64));
+        Date64Type::from_naive_date(res)
+    }
+
+    /// Subtract the given IntervalMonthDayNanoType to an arrow Date64Type
+    ///
+    /// # Arguments
+    ///
+    /// * `date` - The date on which to perform the operation
+    /// * `delta` - The interval to subtract
+    pub fn subtract_month_day_nano(
+        date: <Date64Type as ArrowPrimitiveType>::Native,
+        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
+    ) -> <Date64Type as ArrowPrimitiveType>::Native {
+        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
+        let res = Date64Type::to_naive_date(date);
+        let res = shift_months(res, -months);
+        let res = res.add(Duration::days(-days as i64));
+        let res = res.add(Duration::nanoseconds(-nanos));
+        Date64Type::from_naive_date(res)
+    }
 }
 
 /// Crate private types for Decimal Arrays

Reply via email to