env_logger/fmt/humantime.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
use std::fmt;
use std::time::SystemTime;
use crate::fmt::{Formatter, TimestampPrecision};
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())
/// });
/// ```
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`]: std::fmt::Display
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 fmt::Debug for TimestampValue<'_> {
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 Ok(ts) = jiff::Timestamp::try_from(self.time) else {
return Err(fmt::Error);
};
match self.precision {
TimestampPrecision::Seconds => write!(f, "{ts:.0}"),
TimestampPrecision::Millis => write!(f, "{ts:.3}"),
TimestampPrecision::Micros => write!(f, "{ts:.6}"),
TimestampPrecision::Nanos => write!(f, "{ts:.9}"),
}
}
}
#[cfg(test)]
mod tests {
use super::Timestamp;
use crate::TimestampPrecision;
#[test]
fn test_display_timestamp() {
let mut ts = Timestamp {
time: std::time::SystemTime::UNIX_EPOCH,
precision: TimestampPrecision::Nanos,
};
assert_eq!("1970-01-01T00:00:00.000000000Z", format!("{ts}"));
ts.precision = TimestampPrecision::Micros;
assert_eq!("1970-01-01T00:00:00.000000Z", format!("{ts}"));
ts.precision = TimestampPrecision::Millis;
assert_eq!("1970-01-01T00:00:00.000Z", format!("{ts}"));
ts.precision = TimestampPrecision::Seconds;
assert_eq!("1970-01-01T00:00:00Z", format!("{ts}"));
}
}