use super::Zone;
use crate::prelude::*;
use chrono::{Datelike, TimeZone};
#[derive(Clone, Copy, Eq, From, Into, Ord, PartialEq, PartialOrd)]
pub struct Date(chrono::NaiveDate);
impl Date {
pub fn from_ymd(year: isize, month: usize, day: usize) -> Self {
Self(chrono::NaiveDate::from_ymd(year as i32, month as u32, day as u32))
}
pub fn and_hms(&self, hour: usize, minute: usize, second: usize, zone: Zone) -> Time {
let inner = match &zone {
Zone::Local => chrono::Local
.from_local_date(&self.0)
.and_hms_opt(hour as u32, minute as u32, second as u32)
.unwrap()
.with_timezone(&chrono::Utc),
Zone::Tz(tz) => tz
.from_local_date(&self.0)
.and_hms_opt(hour as u32, minute as u32, second as u32)
.unwrap()
.with_timezone(&chrono::Utc),
};
Time { inner, zone }
}
pub fn day(&self) -> usize {
self.0.day() as usize
}
pub fn format<'a>(&self, fmt: &'a str) -> impl Display + 'a {
self.0.format(fmt)
}
pub fn month(&self) -> usize {
self.0.month() as usize
}
pub fn next(&self) -> Self {
Self(self.0.succ())
}
pub fn prev(&self) -> Self {
Self(self.0.pred())
}
pub fn to_local_time(&self) -> Time {
self.to_time(super::LOCAL)
}
pub fn to_time(&self, zone: Zone) -> Time {
self.and_hms(0, 0, 0, zone)
}
pub fn to_utc_time(&self) -> Time {
self.to_time(super::UTC)
}
pub fn year(&self) -> isize {
self.0.year() as isize
}
pub fn ymd(&self) -> (isize, usize, usize) {
(self.year(), self.month(), self.day())
}
}
impl Debug for Date {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "\"{}\"", self.format("%F"))
}
}
impl Display for Date {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.format("%v"))
}
}
cfg_if! {
if #[cfg(feature = "postgres")] {
use postgres_types as pg;
impl<'a> pg::FromSql<'a> for Date {
fn from_sql(ty: &pg::Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>>{
Ok(Self(pg::FromSql::from_sql(ty, raw)?))
}
fn accepts(ty: &pg::Type) -> bool {
<chrono::NaiveDate as pg::FromSql>::accepts(ty)
}
}
impl pg::ToSql for Date {
fn to_sql(&self, ty: &pg::Type, out: &mut bytes::BytesMut) -> Result<pg::IsNull, Box<dyn Error + Sync + Send>>
where
Self: Sized,
{
self.0.to_sql(ty, out)
}
fn accepts(ty: &pg::Type) -> bool
where
Self: Sized,
{
<chrono::NaiveDate as pg::ToSql>::accepts(ty)
}
fn to_sql_checked(&self, ty: &pg::Type, out: &mut bytes::BytesMut) -> Result<pg::IsNull, Box<dyn Error + Sync + Send>> {
self.0.to_sql_checked(ty, out)
}
}
}
}