use crate::pg_interval::interval::Interval;
use crate::pg_interval::interval_parse::parse_error::ParseError;
pub struct IntervalNorm {
pub years: i32,
pub months: i32,
pub days: i32,
pub hours: i64,
pub minutes: i64,
pub seconds: i64,
pub microseconds: i64,
}
impl From<Interval> for IntervalNorm {
fn from(val: Interval) -> IntervalNorm {
let months = val.months;
let days = val.days;
let microseconds = val.microseconds;
let years = (months - (months % 12)) / 12;
let months = months - years * 12;
let hours = (microseconds - (microseconds % 3_600_000_000)) / 3_600_000_000;
let microseconds = microseconds - hours * 3_600_000_000;
let minutes = (microseconds - (microseconds % 60_000_000)) / 60_000_000;
let microseconds = microseconds - minutes * 60_000_000;
let seconds = (microseconds - (microseconds % 1_000_000)) / 1_000_000;
let microseconds = microseconds - seconds * 1_000_000;
IntervalNorm {
years,
months,
days,
hours,
minutes,
seconds,
microseconds,
}
}
}
impl IntervalNorm {
pub fn try_into_interval(self) -> Result<Interval, ParseError> {
let months = self
.years
.checked_mul(12)
.and_then(|years| self.months.checked_add(years));
let microseconds = self
.hours
.checked_mul(60)
.and_then(|minutes| self.minutes.checked_add(minutes))
.and_then(|minutes| minutes.checked_mul(60))
.and_then(|seconds| self.seconds.checked_add(seconds))
.and_then(|seconds| seconds.checked_mul(1_000_000))
.and_then(|microseconds| self.microseconds.checked_add(microseconds));
Ok(Interval {
months: months.ok_or_else(|| {
ParseError::from_year_month("Invalid year/month interval overflow detected.")
})?,
days: self.days,
microseconds: microseconds
.ok_or_else(|| ParseError::from_time("Invalid time interval overflow detected."))?,
})
}
pub fn default() -> IntervalNorm {
IntervalNorm {
years: 0,
months: 0,
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
microseconds: 0,
}
}
pub fn is_zeroed(&self) -> bool {
self.years == 0
&& self.months == 0
&& self.days == 0
&& self.hours == 0
&& self.minutes == 0
&& self.seconds == 0
&& self.microseconds == 0
}
pub fn is_time_interval_pos(&self) -> bool {
self.hours > 0 || self.minutes > 0 || self.seconds > 0 || self.microseconds > 0
}
pub fn is_time_present(&self) -> bool {
self.hours != 0 || self.minutes != 0 || self.seconds != 0 || self.microseconds != 0
}
}