#[cfg(feature = "chrono")]
mod chrono;
#[cfg(feature = "jiff")]
mod jiff;
#[cfg(feature = "time")]
pub type Time = time::Time;
#[cfg(feature = "time")]
pub type Timezone = time::UtcOffset;
#[cfg(feature = "time")]
pub type TimeTz = (Time, Timezone);
#[cfg(feature = "time")]
impl crate::ToSql for Time {
fn ty(&self) -> crate::pq::Type {
crate::pq::types::TIME
}
fn to_text(&self) -> crate::Result<Option<String>> {
self.to_string().to_text()
}
fn to_binary(&self) -> crate::Result<Option<Vec<u8>>> {
let usecs = self.hour() as i64 * 60 * 60 * 1_000_000
+ self.minute() as i64 * 60 * 1_000_000
+ self.second() as i64 * 1_000_000
+ self.millisecond() as i64 * 1_000
+ self.microsecond() as i64;
let mut buf = Vec::new();
crate::to_sql::write_i64(&mut buf, usecs)?;
Ok(Some(buf))
}
}
#[cfg(feature = "time")]
impl crate::FromSql for Time {
fn from_text(ty: &crate::pq::Type, raw: Option<&str>) -> crate::Result<Self> {
let format = time::macros::format_description!("[hour]:[minute]:[second]");
Time::parse(crate::from_sql::not_null(raw)?, &format).map_err(|_| Self::error(ty, raw))
}
fn from_binary(ty: &crate::pq::Type, raw: Option<&[u8]>) -> crate::Result<Self> {
let usec = i64::from_binary(ty, raw)?;
Ok(Time::MIDNIGHT + time::Duration::microseconds(usec))
}
}
#[cfg(feature = "time")]
impl crate::entity::Simple for Time {}
#[cfg(feature = "time")]
impl crate::ToSql for TimeTz {
fn ty(&self) -> crate::pq::Type {
crate::pq::types::TIMETZ
}
fn to_text(&self) -> crate::Result<Option<String>> {
format!("{}{}", self.0, self.1).to_text()
}
fn to_binary(&self) -> crate::Result<Option<Vec<u8>>> {
let mut buf = self.0.to_binary()?.unwrap();
crate::to_sql::write_i32(&mut buf, -self.1.whole_seconds())?;
Ok(Some(buf))
}
}
#[cfg(feature = "time")]
impl crate::FromSql for TimeTz {
fn from_text(ty: &crate::pq::Type, raw: Option<&str>) -> crate::Result<Self> {
let value = crate::from_sql::not_null(raw)?;
let x = match value.find(['+', '-']) {
Some(x) => x,
None => return Err(Self::error(ty, raw)),
};
let format = time::macros::format_description!("[hour]:[minute]:[second]");
let time = Time::parse(&value[0..x], &format).map_err(|_| Self::error(ty, raw))?;
let mut tz = value[x..].replace(':', "");
if tz.len() == 3 {
tz.push_str("00");
}
let format = time::macros::format_description!("[offset_hour][offset_minute]");
let timezone = Timezone::parse(&tz, &format).map_err(|_| Self::error(ty, raw))?;
Ok((time, timezone))
}
fn from_binary(ty: &crate::pq::Type, raw: Option<&[u8]>) -> crate::Result<Self> {
let mut buf = crate::from_sql::not_null(raw)?;
let time = crate::from_sql::read_i64(&mut buf)?;
let zone = crate::from_sql::read_i32(&mut buf)?;
Ok((
Time::MIDNIGHT + time::Duration::microseconds(time),
Timezone::from_whole_seconds(-zone).map_err(|_| Self::error(ty, raw))?,
))
}
}
#[cfg(feature = "time")]
impl crate::entity::Simple for TimeTz {}
#[cfg(all(test, feature = "time"))]
mod test {
crate::sql_test!(
time,
crate::Time,
[
("'00:00:00'", crate::Time::MIDNIGHT),
("'01:02:03'", time::macros::time!(01:02:03)),
]
);
crate::sql_test!(
timetz,
crate::TimeTz,
[
(
"'00:00:00+0000'",
(crate::Time::MIDNIGHT, crate::Timezone::UTC)
),
(
"'01:02:03+0200'",
(time::macros::time!(01:02:03), time::macros::offset!(+2))
),
]
);
}