use std::fmt; use std::time::SystemTime; use humantime::{ format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos, format_rfc3339_seconds, }; use crate::fmt::{Formatter, TimestampPrecision}; pub(in crate::fmt) mod glob { pub use super::*; } impl Formatter { /// Get a [`Timestamp`] for the current date and time in UTC. /// /// # Examples /// /// Include the current timestamp with the log record: /// /// ``` /// use std::io::Write; /// /// let mut builder = env_logger::Builder::new(); /// /// builder.format(|buf, record| { /// let ts = buf.timestamp(); /// /// writeln!(buf, "{}: {}: {}", ts, record.level(), record.args()) /// }); /// ``` /// /// [`Timestamp`]: struct.Timestamp.html pub fn timestamp(&self) -> Timestamp { Timestamp { time: SystemTime::now(), precision: TimestampPrecision::Seconds, } } /// Get a [`Timestamp`] for the current date and time in UTC with full /// second precision. pub fn timestamp_seconds(&self) -> Timestamp { Timestamp { time: SystemTime::now(), precision: TimestampPrecision::Seconds, } } /// Get a [`Timestamp`] for the current date and time in UTC with /// millisecond precision. pub fn timestamp_millis(&self) -> Timestamp { Timestamp { time: SystemTime::now(), precision: TimestampPrecision::Millis, } } /// Get a [`Timestamp`] for the current date and time in UTC with /// microsecond precision. pub fn timestamp_micros(&self) -> Timestamp { Timestamp { time: SystemTime::now(), precision: TimestampPrecision::Micros, } } /// Get a [`Timestamp`] for the current date and time in UTC with /// nanosecond precision. pub fn timestamp_nanos(&self) -> Timestamp { Timestamp { time: SystemTime::now(), precision: TimestampPrecision::Nanos, } } } /// An [RFC3339] formatted timestamp. /// /// The timestamp implements [`Display`] and can be written to a [`Formatter`]. /// /// [RFC3339]: https://www.ietf.org/rfc/rfc3339.txt /// [`Display`]: https://doc.rust-lang.org/stable/std/fmt/trait.Display.html /// [`Formatter`]: struct.Formatter.html pub struct Timestamp { time: SystemTime, precision: TimestampPrecision, } impl fmt::Debug for Timestamp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { /// A `Debug` wrapper for `Timestamp` that uses the `Display` implementation. struct TimestampValue<'a>(&'a Timestamp); impl<'a> fmt::Debug for TimestampValue<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } f.debug_tuple("Timestamp") .field(&TimestampValue(self)) .finish() } } impl fmt::Display for Timestamp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let formatter = match self.precision { TimestampPrecision::Seconds => format_rfc3339_seconds, TimestampPrecision::Millis => format_rfc3339_millis, TimestampPrecision::Micros => format_rfc3339_micros, TimestampPrecision::Nanos => format_rfc3339_nanos, }; formatter(self.time).fmt(f) } }