use std::fmt;
use std::time::Instant;
#[cfg(not(feature = "chrono"))]
mod datetime;
pub trait FormatTime {
fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result;
}
pub fn time() -> SystemTime {
SystemTime::default()
}
pub fn uptime() -> Uptime {
Uptime::default()
}
impl<'a, F> FormatTime for &'a F
where
F: FormatTime,
{
fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result {
(*self).format_time(w)
}
}
impl FormatTime for () {
fn format_time(&self, _: &mut dyn fmt::Write) -> fmt::Result {
Ok(())
}
}
impl FormatTime for fn(&mut dyn fmt::Write) -> fmt::Result {
fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result {
(*self)(w)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
pub struct SystemTime;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Uptime {
epoch: Instant,
}
impl Default for Uptime {
fn default() -> Self {
Uptime {
epoch: Instant::now(),
}
}
}
impl From<Instant> for Uptime {
fn from(epoch: Instant) -> Self {
Uptime { epoch }
}
}
#[cfg(feature = "chrono")]
impl FormatTime for SystemTime {
fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result {
write!(w, "{}", chrono::Local::now().format("%b %d %H:%M:%S%.3f"))
}
}
#[cfg(not(feature = "chrono"))]
impl FormatTime for SystemTime {
fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result {
write!(
w,
"{}",
datetime::DateTime::from(std::time::SystemTime::now())
)
}
}
impl FormatTime for Uptime {
fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result {
let e = self.epoch.elapsed();
write!(w, "{:4}.{:09}s", e.as_secs(), e.subsec_nanos())
}
}
#[cfg(feature = "chrono")]
#[derive(Debug, Clone, Eq, PartialEq)]
enum ChronoFmtType {
Rfc3339,
Custom(String),
}
#[cfg(feature = "chrono")]
impl Default for ChronoFmtType {
fn default() -> Self {
ChronoFmtType::Rfc3339
}
}
#[cfg(feature = "chrono")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct ChronoUtc {
format: ChronoFmtType,
}
#[cfg(feature = "chrono")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
impl ChronoUtc {
pub fn rfc3339() -> Self {
ChronoUtc {
format: ChronoFmtType::Rfc3339,
}
}
pub fn with_format(format_string: String) -> Self {
ChronoUtc {
format: ChronoFmtType::Custom(format_string),
}
}
}
#[cfg(feature = "chrono")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
impl FormatTime for ChronoUtc {
fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result {
let time = chrono::Utc::now();
match self.format {
ChronoFmtType::Rfc3339 => write!(w, "{}", time.to_rfc3339()),
ChronoFmtType::Custom(ref format_str) => write!(w, "{}", time.format(format_str)),
}
}
}
#[cfg(feature = "chrono")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct ChronoLocal {
format: ChronoFmtType,
}
#[cfg(feature = "chrono")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
impl ChronoLocal {
pub fn rfc3339() -> Self {
ChronoLocal {
format: ChronoFmtType::Rfc3339,
}
}
pub fn with_format(format_string: String) -> Self {
ChronoLocal {
format: ChronoFmtType::Custom(format_string),
}
}
}
#[cfg(feature = "chrono")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
impl FormatTime for ChronoLocal {
fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result {
let time = chrono::Local::now();
match self.format {
ChronoFmtType::Rfc3339 => write!(w, "{}", time.to_rfc3339()),
ChronoFmtType::Custom(ref format_str) => write!(w, "{}", time.format(format_str)),
}
}
}