1 use std::fmt;
2 use std::time::SystemTime;
3 
4 use humantime::{
5     format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos, format_rfc3339_seconds,
6 };
7 
8 use crate::fmt::{Formatter, TimestampPrecision};
9 
10 pub(in crate::fmt) mod glob {
11     pub use super::*;
12 }
13 
14 impl Formatter {
15     /// Get a [`Timestamp`] for the current date and time in UTC.
16     ///
17     /// # Examples
18     ///
19     /// Include the current timestamp with the log record:
20     ///
21     /// ```
22     /// use std::io::Write;
23     ///
24     /// let mut builder = env_logger::Builder::new();
25     ///
26     /// builder.format(|buf, record| {
27     ///     let ts = buf.timestamp();
28     ///
29     ///     writeln!(buf, "{}: {}: {}", ts, record.level(), record.args())
30     /// });
31     /// ```
32     ///
33     /// [`Timestamp`]: struct.Timestamp.html
timestamp(&self) -> Timestamp34     pub fn timestamp(&self) -> Timestamp {
35         Timestamp {
36             time: SystemTime::now(),
37             precision: TimestampPrecision::Seconds,
38         }
39     }
40 
41     /// Get a [`Timestamp`] for the current date and time in UTC with full
42     /// second precision.
timestamp_seconds(&self) -> Timestamp43     pub fn timestamp_seconds(&self) -> Timestamp {
44         Timestamp {
45             time: SystemTime::now(),
46             precision: TimestampPrecision::Seconds,
47         }
48     }
49 
50     /// Get a [`Timestamp`] for the current date and time in UTC with
51     /// millisecond precision.
timestamp_millis(&self) -> Timestamp52     pub fn timestamp_millis(&self) -> Timestamp {
53         Timestamp {
54             time: SystemTime::now(),
55             precision: TimestampPrecision::Millis,
56         }
57     }
58 
59     /// Get a [`Timestamp`] for the current date and time in UTC with
60     /// microsecond precision.
timestamp_micros(&self) -> Timestamp61     pub fn timestamp_micros(&self) -> Timestamp {
62         Timestamp {
63             time: SystemTime::now(),
64             precision: TimestampPrecision::Micros,
65         }
66     }
67 
68     /// Get a [`Timestamp`] for the current date and time in UTC with
69     /// nanosecond precision.
timestamp_nanos(&self) -> Timestamp70     pub fn timestamp_nanos(&self) -> Timestamp {
71         Timestamp {
72             time: SystemTime::now(),
73             precision: TimestampPrecision::Nanos,
74         }
75     }
76 }
77 
78 /// An [RFC3339] formatted timestamp.
79 ///
80 /// The timestamp implements [`Display`] and can be written to a [`Formatter`].
81 ///
82 /// [RFC3339]: https://www.ietf.org/rfc/rfc3339.txt
83 /// [`Display`]: https://doc.rust-lang.org/stable/std/fmt/trait.Display.html
84 /// [`Formatter`]: struct.Formatter.html
85 pub struct Timestamp {
86     time: SystemTime,
87     precision: TimestampPrecision,
88 }
89 
90 impl fmt::Debug for Timestamp {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result91     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92         /// A `Debug` wrapper for `Timestamp` that uses the `Display` implementation.
93         struct TimestampValue<'a>(&'a Timestamp);
94 
95         impl<'a> fmt::Debug for TimestampValue<'a> {
96             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97                 fmt::Display::fmt(&self.0, f)
98             }
99         }
100 
101         f.debug_tuple("Timestamp")
102             .field(&TimestampValue(&self))
103             .finish()
104     }
105 }
106 
107 impl fmt::Display for Timestamp {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result108     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109         let formatter = match self.precision {
110             TimestampPrecision::Seconds => format_rfc3339_seconds,
111             TimestampPrecision::Millis => format_rfc3339_millis,
112             TimestampPrecision::Micros => format_rfc3339_micros,
113             TimestampPrecision::Nanos => format_rfc3339_nanos,
114         };
115 
116         formatter(self.time).fmt(f)
117     }
118 }
119