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