use crate::fmt::{format::Writer, time::FormatTime, writer::WriteAdaptor};
use std::fmt;
use time::{format_description::well_known, formatting::Formattable, OffsetDateTime, UtcOffset};
#[derive(Clone, Debug)]
#[cfg_attr(
docsrs,
doc(cfg(all(unsound_local_offset, feature = "time", feature = "local-time")))
)]
#[cfg(feature = "local-time")]
pub struct LocalTime<F> {
format: F,
}
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
#[derive(Clone, Debug)]
pub struct UtcTime<F> {
format: F,
}
#[derive(Clone, Debug)]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
pub struct OffsetTime<F> {
offset: time::UtcOffset,
format: F,
}
#[cfg(feature = "local-time")]
impl LocalTime<well_known::Rfc3339> {
pub fn rfc_3339() -> Self {
Self::new(well_known::Rfc3339)
}
}
#[cfg(feature = "local-time")]
impl<F: Formattable> LocalTime<F> {
pub fn new(format: F) -> Self {
Self { format }
}
}
#[cfg(feature = "local-time")]
impl<F> FormatTime for LocalTime<F>
where
F: Formattable,
{
fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
let now = OffsetDateTime::now_local().map_err(|_| fmt::Error)?;
format_datetime(now, w, &self.format)
}
}
#[cfg(feature = "local-time")]
impl<F> Default for LocalTime<F>
where
F: Formattable + Default,
{
fn default() -> Self {
Self::new(F::default())
}
}
impl UtcTime<well_known::Rfc3339> {
pub fn rfc_3339() -> Self {
Self::new(well_known::Rfc3339)
}
}
impl<F: Formattable> UtcTime<F> {
pub fn new(format: F) -> Self {
Self { format }
}
}
impl<F> FormatTime for UtcTime<F>
where
F: Formattable,
{
fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
format_datetime(OffsetDateTime::now_utc(), w, &self.format)
}
}
impl<F> Default for UtcTime<F>
where
F: Formattable + Default,
{
fn default() -> Self {
Self::new(F::default())
}
}
#[cfg(feature = "local-time")]
impl OffsetTime<well_known::Rfc3339> {
pub fn local_rfc_3339() -> Result<Self, time::error::IndeterminateOffset> {
Ok(Self::new(
UtcOffset::current_local_offset()?,
well_known::Rfc3339,
))
}
}
impl<F: time::formatting::Formattable> OffsetTime<F> {
pub fn new(offset: time::UtcOffset, format: F) -> Self {
Self { offset, format }
}
}
impl<F> FormatTime for OffsetTime<F>
where
F: time::formatting::Formattable,
{
fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
let now = OffsetDateTime::now_utc().to_offset(self.offset);
format_datetime(now, w, &self.format)
}
}
fn format_datetime(
now: OffsetDateTime,
into: &mut Writer<'_>,
fmt: &impl Formattable,
) -> fmt::Result {
let mut into = WriteAdaptor::new(into);
now.format_into(&mut into, fmt)
.map_err(|_| fmt::Error)
.map(|_| ())
}