#![allow(warnings)]
use crate::{
error::{err, Error},
util::{
rangeint::RFrom,
t::{self, Constant, C},
},
Unit,
};
pub(crate) fn for_span(
unit: Unit,
increment: i64,
) -> Result<t::NoUnits128, Error> {
static LIMIT: &[Constant] = &[
t::NANOS_PER_MICRO,
t::MICROS_PER_MILLI,
t::MILLIS_PER_SECOND,
t::SECONDS_PER_MINUTE,
t::MINUTES_PER_HOUR,
t::HOURS_PER_CIVIL_DAY,
];
if unit >= Unit::Day {
Ok(t::NoUnits128::rfrom(t::NoUnits::new_unchecked(increment)))
} else {
get_with_limit(unit, increment, "span", LIMIT)
}
}
pub(crate) fn for_datetime(
unit: Unit,
increment: i64,
) -> Result<t::NoUnits128, Error> {
static LIMIT: &[Constant] = &[
t::NANOS_PER_MICRO,
t::MICROS_PER_MILLI,
t::MILLIS_PER_SECOND,
t::SECONDS_PER_MINUTE,
t::MINUTES_PER_HOUR,
t::HOURS_PER_CIVIL_DAY,
Constant(2),
];
get_with_limit(unit, increment, "datetime", LIMIT)
}
pub(crate) fn for_time(
unit: Unit,
increment: i64,
) -> Result<t::NoUnits128, Error> {
static LIMIT: &[Constant] = &[
t::NANOS_PER_MICRO,
t::MICROS_PER_MILLI,
t::MILLIS_PER_SECOND,
t::SECONDS_PER_MINUTE,
t::MINUTES_PER_HOUR,
t::HOURS_PER_CIVIL_DAY,
];
get_with_limit(unit, increment, "time", LIMIT)
}
pub(crate) fn for_timestamp(
unit: Unit,
increment: i64,
) -> Result<t::NoUnits128, Error> {
static MAX: &[Constant] = &[
t::NANOS_PER_CIVIL_DAY,
t::MICROS_PER_CIVIL_DAY,
t::MILLIS_PER_CIVIL_DAY,
t::SECONDS_PER_CIVIL_DAY,
t::MINUTES_PER_CIVIL_DAY,
t::HOURS_PER_CIVIL_DAY,
];
get_with_max(unit, increment, "timestamp", MAX)
}
fn get_with_limit(
unit: Unit,
increment: i64,
what: &'static str,
limit: &[t::Constant],
) -> Result<t::NoUnits128, Error> {
let increment = t::NoUnits::new_unchecked(increment);
if increment <= 0 {
return Err(err!(
"rounding increment {increment} for {unit} must be \
greater than zero",
unit = unit.plural(),
));
}
let Some(must_divide) = limit.get(unit as usize) else {
return Err(err!(
"{what} rounding does not support {unit}",
unit = unit.plural()
));
};
let must_divide = t::NoUnits::rfrom(*must_divide);
if increment >= must_divide || must_divide % increment != C(0) {
Err(err!(
"increment {increment} for rounding {what} to {unit} \
must be 1) less than {must_divide}, 2) divide into \
it evenly and 3) greater than zero",
unit = unit.plural(),
))
} else {
Ok(t::NoUnits128::rfrom(increment))
}
}
fn get_with_max(
unit: Unit,
increment: i64,
what: &'static str,
max: &[t::Constant],
) -> Result<t::NoUnits128, Error> {
let increment = t::NoUnits::new_unchecked(increment);
if increment <= 0 {
return Err(err!(
"rounding increment {increment} for {unit} must be \
greater than zero",
unit = unit.plural(),
));
}
let Some(must_divide) = max.get(unit as usize) else {
return Err(err!(
"{what} rounding does not support {unit}",
unit = unit.plural()
));
};
let must_divide = t::NoUnits::rfrom(*must_divide);
if increment > must_divide || must_divide % increment != C(0) {
Err(err!(
"increment {increment} for rounding {what} to {unit} \
must be 1) less than or equal to {must_divide}, \
2) divide into it evenly and 3) greater than zero",
unit = unit.plural(),
))
} else {
Ok(t::NoUnits128::rfrom(increment))
}
}