1use std::fmt;
2use std::time::SystemTime;
3
4use humantime::{
5 format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos, format_rfc3339_seconds,
6};
7
8use crate::fmt::{Formatter, TimestampPrecision};
9
10impl 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 pub fn timestamp(&self) -> Timestamp {
29 Timestamp {
30 time: SystemTime::now(),
31 precision: TimestampPrecision::Seconds,
32 }
33 }
34
35 /// Get a [`Timestamp`] for the current date and time in UTC with full
36 /// second precision.
37 pub fn timestamp_seconds(&self) -> Timestamp {
38 Timestamp {
39 time: SystemTime::now(),
40 precision: TimestampPrecision::Seconds,
41 }
42 }
43
44 /// Get a [`Timestamp`] for the current date and time in UTC with
45 /// millisecond precision.
46 pub fn timestamp_millis(&self) -> Timestamp {
47 Timestamp {
48 time: SystemTime::now(),
49 precision: TimestampPrecision::Millis,
50 }
51 }
52
53 /// Get a [`Timestamp`] for the current date and time in UTC with
54 /// microsecond precision.
55 pub fn timestamp_micros(&self) -> Timestamp {
56 Timestamp {
57 time: SystemTime::now(),
58 precision: TimestampPrecision::Micros,
59 }
60 }
61
62 /// Get a [`Timestamp`] for the current date and time in UTC with
63 /// nanosecond precision.
64 pub fn timestamp_nanos(&self) -> Timestamp {
65 Timestamp {
66 time: SystemTime::now(),
67 precision: TimestampPrecision::Nanos,
68 }
69 }
70}
71
72/// An [RFC3339] formatted timestamp.
73///
74/// The timestamp implements [`Display`] and can be written to a [`Formatter`].
75///
76/// [RFC3339]: https://www.ietf.org/rfc/rfc3339.txt
77/// [`Display`]: std::fmt::Display
78pub struct Timestamp {
79 time: SystemTime,
80 precision: TimestampPrecision,
81}
82
83impl fmt::Debug for Timestamp {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 /// A `Debug` wrapper for `Timestamp` that uses the `Display` implementation.
86 struct TimestampValue<'a>(&'a Timestamp);
87
88 impl fmt::Debug for TimestampValue<'_> {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 fmt::Display::fmt(&self.0, f)
91 }
92 }
93
94 f&mut DebugTuple<'_, '_>.debug_tuple(name:"Timestamp")
95 .field(&TimestampValue(self))
96 .finish()
97 }
98}
99
100impl fmt::Display for Timestamp {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 let formatter: fn(SystemTime) -> Rfc3339Timestamp = match self.precision {
103 TimestampPrecision::Seconds => format_rfc3339_seconds,
104 TimestampPrecision::Millis => format_rfc3339_millis,
105 TimestampPrecision::Micros => format_rfc3339_micros,
106 TimestampPrecision::Nanos => format_rfc3339_nanos,
107 };
108
109 formatter(self.time).fmt(f)
110 }
111}
112