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)
}