use crate::common::{
is_valid_time, HOURS_PER_DAY, MINUTES_PER_HOUR, SECONDS_PER_MINUTE, USECONDS_MAX,
USECONDS_PER_DAY, USECONDS_PER_HOUR, USECONDS_PER_MINUTE, USECONDS_PER_SECOND,
};
use crate::error::{Error, Result};
use crate::format::{Formatter, LazyFormat, NaiveDateTime};
use crate::{Date, DateTime, IntervalDT, Timestamp};
use std::cmp::Ordering;
use std::convert::TryFrom;
use std::fmt::Display;
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[repr(transparent)]
pub struct Time(i64);
impl Time {
pub const ZERO: Self = unsafe { Time::from_hms_unchecked(0, 0, 0, 0) };
pub const MAX: Self = unsafe { Time::from_hms_unchecked(23, 59, 59, 999999) };
#[inline]
pub const unsafe fn from_hms_unchecked(hour: u32, minute: u32, sec: u32, usec: u32) -> Time {
let time = hour as i64 * USECONDS_PER_HOUR
+ minute as i64 * USECONDS_PER_MINUTE
+ sec as i64 * USECONDS_PER_SECOND
+ usec as i64;
Time(time)
}
#[inline]
pub const fn try_from_hms(hour: u32, minute: u32, sec: u32, usec: u32) -> Result<Time> {
if hour >= HOURS_PER_DAY {
return Err(Error::TimeOutOfRange);
}
if minute >= MINUTES_PER_HOUR {
return Err(Error::InvalidMinute);
}
if sec >= SECONDS_PER_MINUTE {
return Err(Error::InvalidSecond);
}
if usec > USECONDS_MAX {
return Err(Error::InvalidFraction);
}
Ok(unsafe { Time::from_hms_unchecked(hour, minute, sec, usec) })
}
#[inline]
pub const fn is_valid(hour: u32, minute: u32, sec: u32, usec: u32) -> bool {
if hour >= HOURS_PER_DAY {
return false;
}
if minute >= MINUTES_PER_HOUR {
return false;
}
if sec >= SECONDS_PER_MINUTE {
return false;
}
if usec > USECONDS_MAX {
return false;
}
true
}
#[inline]
pub(crate) const fn validate_hms(hour: u32, minute: u32, sec: u32) -> Result<()> {
if hour >= HOURS_PER_DAY {
return Err(Error::TimeOutOfRange);
}
if minute >= MINUTES_PER_HOUR {
return Err(Error::InvalidMinute);
}
if sec >= SECONDS_PER_MINUTE {
return Err(Error::InvalidSecond);
}
Ok(())
}
#[inline(always)]
pub const fn usecs(self) -> i64 {
self.0
}
#[inline(always)]
pub const unsafe fn from_usecs_unchecked(usecs: i64) -> Self {
Time(usecs)
}
#[allow(dead_code)]
#[inline]
pub const fn try_from_usecs(usecs: i64) -> Result<Self> {
if is_valid_time(usecs) {
Ok(unsafe { Time::from_usecs_unchecked(usecs) })
} else {
Err(Error::TimeOutOfRange)
}
}
#[inline]
pub const fn extract(self) -> (u32, u32, u32, u32) {
let mut time = self.0;
let hour = (time / USECONDS_PER_HOUR) as u32;
time -= hour as i64 * USECONDS_PER_HOUR;
let minute = (time / USECONDS_PER_MINUTE) as u32;
time -= minute as i64 * USECONDS_PER_MINUTE;
let sec = (time / USECONDS_PER_SECOND) as u32;
time -= sec as i64 * USECONDS_PER_SECOND;
let usec = time as u32;
(hour, minute, sec, usec)
}
#[inline]
pub fn format<S: AsRef<str>>(self, fmt: S) -> Result<impl Display> {
let fmt = Formatter::try_new(fmt)?;
Ok(LazyFormat::new(fmt, self))
}
#[inline]
pub fn parse<S1: AsRef<str>, S2: AsRef<str>>(input: S1, fmt: S2) -> Result<Self> {
let fmt = Formatter::try_new(fmt)?;
fmt.parse(input)
}
#[inline]
pub const fn sub_time(self, time: Time) -> IntervalDT {
unsafe { IntervalDT::from_usecs_unchecked(self.usecs() - time.usecs()) }
}
#[inline]
pub const fn add_interval_dt(self, interval: IntervalDT) -> Time {
let temp_result = self.usecs() + interval.usecs() % USECONDS_PER_DAY;
if temp_result >= 0 {
unsafe { Time::from_usecs_unchecked(temp_result % USECONDS_PER_DAY) }
} else {
unsafe { Time::from_usecs_unchecked(temp_result + USECONDS_PER_DAY) }
}
}
#[inline]
pub const fn sub_interval_dt(self, interval: IntervalDT) -> Time {
self.add_interval_dt(interval.negate())
}
#[inline]
pub fn mul_f64(self, number: f64) -> Result<IntervalDT> {
unsafe { IntervalDT::from_usecs_unchecked(self.usecs()).mul_f64(number) }
}
#[inline]
pub fn div_f64(self, number: f64) -> Result<IntervalDT> {
unsafe { IntervalDT::from_usecs_unchecked(self.usecs()).div_f64(number) }
}
}
impl From<Time> for NaiveDateTime {
#[inline]
fn from(time: Time) -> Self {
let (hour, minute, sec, usec) = time.extract();
NaiveDateTime {
hour,
minute,
sec,
usec,
..NaiveDateTime::new()
}
}
}
impl From<Timestamp> for Time {
#[inline(always)]
fn from(timestamp: Timestamp) -> Self {
timestamp.time()
}
}
impl From<IntervalDT> for Time {
#[inline(always)]
fn from(interval: IntervalDT) -> Self {
let usec = interval.usecs().abs() % USECONDS_PER_DAY;
unsafe { Time::from_usecs_unchecked(usec) }
}
}
impl PartialEq<IntervalDT> for Time {
#[inline]
fn eq(&self, other: &IntervalDT) -> bool {
self.usecs() == other.usecs()
}
}
impl PartialOrd<IntervalDT> for Time {
#[inline]
fn partial_cmp(&self, other: &IntervalDT) -> Option<Ordering> {
Some(self.usecs().cmp(&other.usecs()))
}
}
impl TryFrom<&NaiveDateTime> for Time {
type Error = Error;
#[inline]
fn try_from(dt: &NaiveDateTime) -> Result<Self> {
Time::validate_hms(dt.hour, dt.minute, dt.sec)?;
let total_usec = dt.hour as i64 * USECONDS_PER_HOUR
+ dt.minute as i64 * USECONDS_PER_MINUTE
+ dt.sec as i64 * USECONDS_PER_SECOND
+ dt.usec as i64;
Time::try_from_usecs(total_usec)
}
}
impl TryFrom<NaiveDateTime> for Time {
type Error = Error;
#[inline]
fn try_from(dt: NaiveDateTime) -> Result<Self> {
Time::try_from(&dt)
}
}
impl DateTime for Time {
#[inline(always)]
fn year(&self) -> Option<i32> {
None
}
#[inline(always)]
fn month(&self) -> Option<i32> {
None
}
#[inline(always)]
fn day(&self) -> Option<i32> {
None
}
#[inline(always)]
fn hour(&self) -> Option<i32> {
Some((self.usecs() / USECONDS_PER_HOUR) as i32)
}
#[inline(always)]
fn minute(&self) -> Option<i32> {
let remain_time = self.usecs() % USECONDS_PER_HOUR;
Some((remain_time / USECONDS_PER_MINUTE) as i32)
}
#[inline(always)]
fn second(&self) -> Option<f64> {
let remain_time = self.usecs() % USECONDS_PER_MINUTE;
Some(remain_time as f64 / USECONDS_PER_SECOND as f64)
}
#[inline(always)]
fn date(&self) -> Option<Date> {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_time() {
assert_eq!(Time::ZERO, Time::try_from_hms(0, 0, 0, 0).unwrap());
assert_eq!(Time::MAX, Time::try_from_hms(23, 59, 59, 999999).unwrap());
let time = Time::try_from_hms(0, 0, 0, 0).unwrap();
assert_eq!(time.usecs(), 0);
assert_eq!(time.extract(), (0, 0, 0, 0));
let time = Time::try_from_hms(23, 59, 59, 999999).unwrap();
assert_eq!(time.usecs(), 86399999999);
assert_eq!(time.extract(), (23, 59, 59, 999999));
let time2 = Time::parse("23:59:59.999999", "HH24:MI:SS.FF").unwrap();
assert_eq!(time2, time);
let time2 = Time::parse("235959999999", "HH24MISSFF").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 0).unwrap();
let time2 = Time::parse("23595", "HH24MISS").unwrap();
assert_eq!(time2, time);
{
assert_eq!(
unsafe { Time::from_hms_unchecked(1, 0, 59, 888889) },
Time::parse("1:0:59.8888885", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
unsafe { Time::from_hms_unchecked(1, 0, 1, 0) },
Time::parse("1:0:0.9999999", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
unsafe { Time::from_hms_unchecked(1, 0, 59, 888889) },
Time::parse("1:0:59.8888885", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
unsafe { Time::from_hms_unchecked(1, 0, 59, 888889) },
Time::parse("1:0:59.8888885", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
unsafe { Time::from_hms_unchecked(1, 1, 0, 0) },
Time::parse("1:0:59.9999995", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
unsafe { Time::from_hms_unchecked(23, 59, 0, 0) },
Time::parse("23:58:59.9999999", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
unsafe { Time::from_hms_unchecked(2, 0, 0, 0) },
Time::parse("1:59:59.9999995", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
unsafe { Time::from_hms_unchecked(1, 0, 59, 888888) },
Time::parse("1:0:59.8888881", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
Time::MAX,
Time::parse("23:59:59.999999", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
Time::MAX,
Time::parse("23:59:59.9999991", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
Time::MAX,
Time::parse("23:59:59.999999119", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
Time::MAX,
Time::parse("23:59:59.9999994", "HH24:MI:SS.FF").unwrap()
);
assert_eq!(
Err(Error::TimeOutOfRange),
Time::parse("24:59:59.9999995", "HH24:MI:SS.FF")
);
assert_eq!(
Err(Error::TimeOutOfRange),
Time::parse("25:59:59.9999995", "HH24:MI:SS.FF")
);
assert_eq!(
Err(Error::InvalidMinute),
Time::parse("23:60:59.9999995", "HH24:MI:SS.FF")
);
assert_eq!(
Err(Error::InvalidSecond),
Time::parse("23:59:60.9999995", "HH24:MI:SS.FF")
);
assert_eq!(
Err(Error::TimeOutOfRange),
Time::parse("23:59:59.9999995", "HH24:MI:SS.FF")
);
assert_eq!(
Err(Error::TimeOutOfRange),
Time::parse("23:59:59.99999999", "HH24:MI:SS.FF")
);
}
{
let time = Time::try_from_hms(12, 59, 5, 12345).unwrap();
let time2 = Time::parse("12:59:5.012345", "HH:MI:SS.FF").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 50000).unwrap();
let time2 = Time::parse("23:59:5.05", "HH24:MI:SS.FF").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 500000).unwrap();
let time2 = Time::parse("23:59:5.5", "HH24:MI:SS.FF").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 123450).unwrap();
let time2 = Time::parse("23:59:5.12345", "HH24:MI:SS.FF").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 123450).unwrap();
let time2 = Time::parse("23:59:5.12345000", "HH24:MI:SS.FF9").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 123450).unwrap();
let time2 = Time::parse("23:59:5.123450", "HH24:MI:SS.FF").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 500).unwrap();
let time2 = Time::parse("23:59:5.0005", "HH24:MI:SS.FF").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 123450).unwrap();
let time2 = Time::parse("23:59:5.12345", "HH24:MI:SS.FF9").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 50000).unwrap();
let time2 = Time::parse("23:59:5.05", "HH24:MI:SS.FF3").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 50000).unwrap();
let time2 = Time::parse("05 23:59:5", "ff3 HH24:MI:SS").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 5, 50000).unwrap();
let fmt = time.format("HH24:MI:SS.FF").unwrap();
assert_eq!(format!("{}", fmt), "23:59:05.050000");
let fmt = time.format("HH24:MI:SS.FF4").unwrap();
assert_eq!(format!("{}", fmt), "23:59:05.0500");
let time = Time::try_from_hms(23, 59, 5, 123456).unwrap();
let fmt = time.format("HH24:MI:SS.FF9").unwrap();
assert_eq!(format!("{}", fmt), "23:59:05.123456000");
}
{
let time = Time::try_from_hms(23, 59, 59, 999999).unwrap();
let time2 = Time::parse("999999 59:23:59", "FF MI:HH24:SS").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(23, 59, 59, 999999).unwrap();
let fmt = time.format("AM MI-HH/SS\\FF4").unwrap();
assert_eq!(format!("{}", fmt), "PM 59-11/59\\9999");
}
{
let time = Time::try_from_hms(0, 0, 1, 0).unwrap();
let time2 = Time::parse("01", "SS").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(0, 0, 0, 0).unwrap();
let time2 = Time::parse("", "HH24:MI:SS").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(11, 0, 0, 0).unwrap();
let time2 = Time::parse("11", "HH24:MI:SS").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(11, 23, 0, 0).unwrap();
let time2 = Time::parse("11:23", "HH24:MI:SS").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(0, 0, 0, 0).unwrap();
let time2 = Time::parse("", "HH:MI:SS").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(11, 0, 0, 0).unwrap();
let time2 = Time::parse("11", "HH:MI:SS").unwrap();
assert_eq!(time2, time);
let time = Time::try_from_hms(11, 23, 0, 0).unwrap();
let time2 = Time::parse("11:23", "HH:MI:SS").unwrap();
assert_eq!(time2, time);
}
{
let time = Time::try_from_hms(7, 8, 9, 10).unwrap();
assert_eq!(format!("{}", time.format("mi").unwrap()), "08");
assert_eq!(format!("{}", time.format("hh").unwrap()), "07");
assert_eq!(format!("{}", time.format("ss").unwrap()), "09");
assert_eq!(format!("{}", time.format("FF").unwrap()), "000010");
}
{
{
let time = Time::parse("", "HH24:MI:SS").unwrap();
assert_eq!(time, Time::try_from_hms(0, 0, 0, 0).unwrap());
let time = Time::parse("", "HH24-MI-SS").unwrap();
assert_eq!(time, Time::try_from_hms(0, 0, 0, 0).unwrap());
let time = Time::parse("11", "HH24:MI:SS").unwrap();
assert_eq!(time, Time::try_from_hms(11, 0, 0, 0).unwrap());
let time = Time::parse("11:23", "HH24:MI:SS").unwrap();
assert_eq!(time, Time::try_from_hms(11, 23, 0, 0).unwrap());
let time = Time::parse("11:23:25", "HH24:MI:SS.ff").unwrap();
assert_eq!(time, Time::try_from_hms(11, 23, 25, 0).unwrap());
}
{
let time = Time::parse("11:00:23", "HH12:MI:SS PM").unwrap();
assert_eq!(time, Time::try_from_hms(11, 0, 23, 0).unwrap());
let time = Time::parse("12:00:23", "HH12:MI:SS PM").unwrap();
assert_eq!(time, Time::try_from_hms(12, 0, 23, 0).unwrap());
let time = Time::parse("1:00:23", "HH12:MI:SS PM").unwrap();
assert_eq!(time, Time::try_from_hms(1, 0, 23, 0).unwrap());
let time = Time::parse("11:00:23", "HH12:MI:SS AM").unwrap();
assert_eq!(time, Time::try_from_hms(11, 0, 23, 0).unwrap());
let time = Time::parse("1:00:23", "HH12:MI:SS AM").unwrap();
assert_eq!(time, Time::try_from_hms(1, 0, 23, 0).unwrap());
let time = Time::parse("12:00:23", "HH12:MI:SS AM").unwrap();
assert_eq!(time, Time::try_from_hms(12, 0, 23, 0).unwrap());
let time = Time::parse("12:00:23", "HH12:MI:SS").unwrap();
assert_eq!(time, Time::try_from_hms(12, 0, 23, 0).unwrap());
}
}
{
assert!(Time::parse("60", "SS").is_err());
assert!(Time::parse("60", "mi").is_err());
assert!(Time::parse("60", "hh").is_err());
assert!(Time::parse("60", "hh").is_err());
assert!(Time::parse("13", "hh").is_err());
assert!(Time::parse("23635", "HHMISS").is_err());
let time = Time::try_from_hms(1, 2, 3, 4).unwrap();
assert!(time.format("testtest").is_err());
assert!(Time::parse("11:12:134", "hh24:mi:ss.ff").is_err());
assert!(Time::parse("11:12134", "hh24:mi:ss.ff").is_err());
}
}
#[test]
fn test_time_sub_time() {
assert_eq!(
Time::try_from_hms(0, 0, 0, 0)
.unwrap()
.sub_time(Time::try_from_hms(1, 2, 3, 4).unwrap()),
-IntervalDT::try_from_dhms(0, 1, 2, 3, 4).unwrap()
);
assert_eq!(
Time::try_from_hms(0, 0, 0, 0)
.unwrap()
.sub_time(Time::try_from_hms(23, 59, 59, 999999).unwrap()),
-IntervalDT::try_from_dhms(0, 23, 59, 59, 999999).unwrap()
);
assert_eq!(
Time::try_from_hms(12, 2, 4, 6)
.unwrap()
.sub_time(Time::try_from_hms(1, 3, 4, 6).unwrap()),
IntervalDT::try_from_dhms(0, 10, 59, 0, 0).unwrap()
);
}
#[test]
fn test_time_add_sub_interval_dt() {
assert_eq!(
Time::try_from_hms(12, 30, 2, 3)
.unwrap()
.add_interval_dt(IntervalDT::try_from_dhms(123, 1, 2, 3, 4).unwrap()),
Time::try_from_hms(13, 32, 5, 7).unwrap()
);
assert_eq!(
Time::try_from_hms(12, 30, 2, 3)
.unwrap()
.add_interval_dt(IntervalDT::try_from_dhms(0, 15, 8, 59, 4).unwrap()),
Time::try_from_hms(3, 39, 1, 7).unwrap()
);
assert_eq!(
Time::try_from_hms(12, 30, 2, 3)
.unwrap()
.sub_interval_dt(IntervalDT::try_from_dhms(123, 15, 8, 59, 4).unwrap()),
Time::try_from_hms(21, 21, 2, 999999).unwrap()
);
assert_eq!(
Time::try_from_hms(12, 30, 2, 3)
.unwrap()
.sub_interval_dt(IntervalDT::try_from_dhms(123, 1, 2, 3, 4).unwrap()),
Time::try_from_hms(11, 27, 58, 999999).unwrap()
);
assert_eq!(
Time::try_from_hms(0, 0, 0, 0)
.unwrap()
.sub_interval_dt(IntervalDT::try_from_dhms(0, 0, 0, 0, 0).unwrap()),
Time::try_from_hms(0, 0, 0, 0).unwrap()
);
assert_eq!(
Time::try_from_hms(0, 0, 0, 0)
.unwrap()
.sub_interval_dt(IntervalDT::try_from_dhms(0, 1, 0, 0, 0).unwrap()),
Time::try_from_hms(23, 0, 0, 0).unwrap()
);
}
#[test]
fn test_time_mul_div() {
assert_eq!(
Time::try_from_hms(1, 2, 3, 4)
.unwrap()
.mul_f64(5.0)
.unwrap(),
IntervalDT::try_from_dhms(0, 5, 10, 15, 20).unwrap()
);
assert_eq!(
Time::try_from_hms(1, 2, 3, 4)
.unwrap()
.mul_f64(-5.2)
.unwrap(),
-IntervalDT::try_from_dhms(0, 5, 22, 39, 600020).unwrap()
);
assert_eq!(
Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.div_f64(-5.2)
.unwrap(),
-IntervalDT::try_from_dhms(0, 0, 23, 40, 0).unwrap()
);
assert_eq!(
Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.div_f64(-5.0)
.unwrap(),
-IntervalDT::try_from_dhms(0, 0, 24, 36, 800001).unwrap()
);
assert_eq!(
Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.div_f64(f64::INFINITY)
.unwrap(),
IntervalDT::try_from_dhms(0, 0, 0, 0, 0).unwrap()
);
assert_eq!(
Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.mul_f64(100.1)
.unwrap(),
IntervalDT::try_from_dhms(8, 13, 18, 58, 400500).unwrap()
);
assert_eq!(
Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.div_f64(-5.1)
.unwrap(),
-IntervalDT::try_from_dhms(0, 0, 24, 7, 843138).unwrap()
);
assert_eq!(
Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.mul_f64(-5.57)
.unwrap(),
-IntervalDT::try_from_dhms(0, 11, 25, 28, 880027).unwrap()
);
assert!(Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.mul_f64(-12345678999999999999.6)
.is_err());
assert!(Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.div_f64(-0.00000000000000001)
.is_err());
assert!(Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.mul_f64(f64::NEG_INFINITY)
.is_err());
assert!(Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.div_f64(f64::NAN)
.is_err());
assert!(Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.mul_f64(f64::NAN)
.is_err());
assert!(Time::try_from_hms(2, 3, 4, 5)
.unwrap()
.div_f64(0.0)
.is_err());
}
#[allow(clippy::float_cmp)]
fn test_extract(hour: u32, min: u32, sec: u32, usec: u32) {
let time = Time::try_from_hms(hour, min, sec, usec).unwrap();
assert_eq!(hour as i32, time.hour().unwrap());
assert_eq!(min as i32, time.minute().unwrap());
assert_eq!(
(sec as f64) + (usec as f64) / 1_000_000f64,
time.second().unwrap()
);
assert!(time.year().is_none());
assert!(time.month().is_none());
assert!(time.day().is_none());
}
#[test]
fn test_time_extract() {
test_extract(0, 0, 0, 0);
test_extract(1, 2, 3, 4);
test_extract(12, 0, 0, 0);
test_extract(16, 34, 59, 356);
test_extract(23, 59, 59, 999999);
}
#[test]
fn test_time_from_interval_dt() {
assert_eq!(Time::ZERO, Time::from(IntervalDT::ZERO));
assert_eq!(Time::ZERO, Time::from(IntervalDT::MIN));
assert_eq!(Time::ZERO, Time::from(IntervalDT::MAX));
assert_eq!(
Time::ZERO,
Time::from(unsafe { IntervalDT::from_dhms_unchecked(0, 0, 0, 0, 0) })
);
assert_eq!(
Time::MAX,
Time::from(unsafe { IntervalDT::from_dhms_unchecked(0, 23, 59, 59, 999999) })
);
assert_eq!(
Time::MAX,
Time::from(unsafe { IntervalDT::from_dhms_unchecked(100, 23, 59, 59, 999999) })
);
assert_eq!(
Time::MAX,
Time::from(unsafe {
IntervalDT::from_dhms_unchecked(100, 23, 59, 59, 999999).negate()
})
);
}
}