use core::fmt::{self, Debug, Formatter};
use crate::calendar::Iso;
use crate::{AsDate, AsTime, Calendar, Date, DateTime, Moment, Month, Offset, PlainTime, Year};
#[derive(Clone, Copy)]
pub struct PlainDateTime<C: Calendar = Iso> {
pub(crate) date: Date<C>,
pub(crate) time: PlainTime,
}
impl<C: Calendar> PlainDateTime<C> {
pub const fn from_moment(calendar: C, moment: Moment) -> Self {
let (secs, nsec) = moment.to_unix();
let date = Date::from_unix_timestamp(calendar, secs);
let time = PlainTime::from_unix_timestamp(secs, nsec);
Self { date, time }
}
}
impl<C: Calendar> PlainDateTime<C> {
#[must_use]
#[inline]
pub const fn calendar(self) -> C {
self.date.calendar()
}
#[must_use]
#[inline]
pub fn year(self) -> Year<C> {
self.date.year()
}
#[must_use]
#[inline]
pub fn month(self) -> Month<C> {
self.date.month()
}
#[must_use]
#[inline]
pub fn day(self) -> u8 {
self.date.day()
}
#[must_use]
#[inline]
pub fn day_of_year(self) -> u16 {
self.date.day_of_year()
}
#[must_use]
#[inline]
pub const fn hour(self) -> u8 {
self.time.hour()
}
#[must_use]
#[inline]
pub const fn minute(self) -> u8 {
self.time.minute()
}
#[must_use]
#[inline]
pub const fn second(self) -> u8 {
self.time.second()
}
#[must_use]
#[inline]
pub const fn millisecond(self) -> u16 {
self.time.millisecond()
}
#[must_use]
#[inline]
pub const fn microsecond(self) -> u32 {
self.time.microsecond()
}
#[must_use]
#[inline]
pub const fn nanosecond(self) -> u32 {
self.time.nanosecond()
}
}
impl<C: Calendar> PlainDateTime<C> {
pub const fn assume_utc(self) -> DateTime<C> {
let (secs, nsec) = self.as_timestamp();
let moment = Moment::from_unix(secs, nsec);
DateTime::from_moment(self.calendar(), moment)
}
pub const fn assume_offset(self, offset: Offset) -> DateTime<C> {
let (mut secs, nsec) = self.as_timestamp();
secs -= offset.as_total_seconds() as i64;
let moment = Moment::from_unix(secs, nsec);
DateTime::from_moment_at_offset(self.calendar(), moment, offset)
}
#[must_use]
pub const fn on<C2: Calendar>(self, calendar: C2) -> PlainDateTime<C2> {
self.with_date(self.date.on(calendar))
}
#[must_use]
pub const fn with_date<C2: Calendar>(self, date: Date<C2>) -> PlainDateTime<C2> {
PlainDateTime {
date,
time: self.time,
}
}
#[must_use]
pub fn with_time<T: Into<PlainTime>>(self, time: T) -> Self {
Self {
date: self.date,
time: time.into(),
}
}
}
impl<C: Calendar> PlainDateTime<C> {
pub(crate) const fn as_timestamp(self) -> (i64, u32) {
let (mut secs, nsec) = self.time.as_timestamp();
secs += self.date.as_days_since_unix_epoch() as i64 * 86_400;
(secs, nsec)
}
}
impl<C: Calendar> Debug for PlainDateTime<C> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.pad(&self.format_rfc3339())
}
}
impl<C: Calendar> AsDate<C> for PlainDateTime<C> {
fn as_date(&self) -> Date<C> {
self.date
}
}
impl<C: Calendar> AsTime for PlainDateTime<C> {
fn as_time(&self) -> PlainTime {
self.time
}
fn as_timestamp(&self) -> (i64, u32) {
(*self).as_timestamp()
}
}