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 ///
29 /// [`Timestamp`]: struct.Timestamp.html
30 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.
39 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.
48 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.
57 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.
66 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
81pub struct Timestamp {
82 time: SystemTime,
83 precision: TimestampPrecision,
84}
85
86impl fmt::Debug for Timestamp {
87 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&mut DebugTuple<'_, '_>.debug_tuple(name:"Timestamp")
98 .field(&TimestampValue(self))
99 .finish()
100 }
101}
102
103impl fmt::Display for Timestamp {
104 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105 let formatter: fn(SystemTime) -> Rfc3339Timestamp = 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