fn add()

in arrow-cast/src/parse.rs [1023:1181]


    fn add(
        &self,
        amount: IntervalAmount,
        unit: IntervalUnit,
    ) -> Result<Self, ArrowError> {
        let result = match unit {
            IntervalUnit::Century => {
                let months_int = amount.integer.mul_checked(100)?.mul_checked(12)?;
                let month_frac = amount.frac * 12 / 10_i64.pow(INTERVAL_PRECISION - 2);
                let months =
                    months_int
                        .add_checked(month_frac)?
                        .try_into()
                        .map_err(|_| {
                            ArrowError::ParseError(format!(
                        "Unable to represent {} centuries as months in a signed 32-bit integer",
                        &amount.integer
                    ))
                        })?;

                Self::new(self.months.add_checked(months)?, self.days, self.nanos)
            }
            IntervalUnit::Decade => {
                let months_int = amount.integer.mul_checked(10)?.mul_checked(12)?;

                let month_frac = amount.frac * 12 / 10_i64.pow(INTERVAL_PRECISION - 1);
                let months =
                    months_int
                        .add_checked(month_frac)?
                        .try_into()
                        .map_err(|_| {
                            ArrowError::ParseError(format!(
                        "Unable to represent {} decades as months in a signed 32-bit integer",
                        &amount.integer
                    ))
                        })?;

                Self::new(self.months.add_checked(months)?, self.days, self.nanos)
            }
            IntervalUnit::Year => {
                let months_int = amount.integer.mul_checked(12)?;
                let month_frac = amount.frac * 12 / 10_i64.pow(INTERVAL_PRECISION);
                let months =
                    months_int
                        .add_checked(month_frac)?
                        .try_into()
                        .map_err(|_| {
                            ArrowError::ParseError(format!(
                        "Unable to represent {} years as months in a signed 32-bit integer",
                        &amount.integer
                    ))
                        })?;

                Self::new(self.months.add_checked(months)?, self.days, self.nanos)
            }
            IntervalUnit::Month => {
                let months = amount.integer.try_into().map_err(|_| {
                    ArrowError::ParseError(format!(
                        "Unable to represent {} months in a signed 32-bit integer",
                        &amount.integer
                    ))
                })?;

                let days = amount.frac * 3 / 10_i64.pow(INTERVAL_PRECISION - 1);
                let days = days.try_into().map_err(|_| {
                    ArrowError::ParseError(format!(
                        "Unable to represent {} months as days in a signed 32-bit integer",
                        amount.frac / 10_i64.pow(INTERVAL_PRECISION)
                    ))
                })?;

                Self::new(
                    self.months.add_checked(months)?,
                    self.days.add_checked(days)?,
                    self.nanos,
                )
            }
            IntervalUnit::Week => {
                let days = amount.integer.mul_checked(7)?.try_into().map_err(|_| {
                    ArrowError::ParseError(format!(
                        "Unable to represent {} weeks as days in a signed 32-bit integer",
                        &amount.integer
                    ))
                })?;

                let nanos =
                    amount.frac * 7 * 24 * 6 * 6 / 10_i64.pow(INTERVAL_PRECISION - 11);

                Self::new(
                    self.months,
                    self.days.add_checked(days)?,
                    self.nanos.add_checked(nanos)?,
                )
            }
            IntervalUnit::Day => {
                let days = amount.integer.try_into().map_err(|_| {
                    ArrowError::InvalidArgumentError(format!(
                        "Unable to represent {} days in a signed 32-bit integer",
                        amount.integer
                    ))
                })?;

                let nanos =
                    amount.frac * 24 * 6 * 6 / 10_i64.pow(INTERVAL_PRECISION - 11);

                Self::new(
                    self.months,
                    self.days.add_checked(days)?,
                    self.nanos.add_checked(nanos)?,
                )
            }
            IntervalUnit::Hour => {
                let nanos_int = amount.integer.mul_checked(NANOS_PER_HOUR)?;
                let nanos_frac =
                    amount.frac * 6 * 6 / 10_i64.pow(INTERVAL_PRECISION - 11);
                let nanos = nanos_int.add_checked(nanos_frac)?;

                Interval::new(self.months, self.days, self.nanos.add_checked(nanos)?)
            }
            IntervalUnit::Minute => {
                let nanos_int = amount.integer.mul_checked(NANOS_PER_MINUTE)?;
                let nanos_frac = amount.frac * 6 / 10_i64.pow(INTERVAL_PRECISION - 10);

                let nanos = nanos_int.add_checked(nanos_frac)?;

                Interval::new(self.months, self.days, self.nanos.add_checked(nanos)?)
            }
            IntervalUnit::Second => {
                let nanos_int = amount.integer.mul_checked(NANOS_PER_SECOND)?;
                let nanos_frac = amount.frac / 10_i64.pow(INTERVAL_PRECISION - 9);
                let nanos = nanos_int.add_checked(nanos_frac)?;

                Interval::new(self.months, self.days, self.nanos.add_checked(nanos)?)
            }
            IntervalUnit::Millisecond => {
                let nanos_int = amount.integer.mul_checked(NANOS_PER_MILLIS)?;
                let nanos_frac = amount.frac / 10_i64.pow(INTERVAL_PRECISION - 6);
                let nanos = nanos_int.add_checked(nanos_frac)?;

                Interval::new(self.months, self.days, self.nanos.add_checked(nanos)?)
            }
            IntervalUnit::Microsecond => {
                let nanos_int = amount.integer.mul_checked(1_000)?;
                let nanos_frac = amount.frac / 10_i64.pow(INTERVAL_PRECISION - 3);
                let nanos = nanos_int.add_checked(nanos_frac)?;

                Interval::new(self.months, self.days, self.nanos.add_checked(nanos)?)
            }
            IntervalUnit::Nanosecond => {
                let nanos_int = amount.integer;
                let nanos_frac = amount.frac / 10_i64.pow(INTERVAL_PRECISION);
                let nanos = nanos_int.add_checked(nanos_frac)?;

                Interval::new(self.months, self.days, self.nanos.add_checked(nanos)?)
            }
        };

        Ok(result)
    }