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
10pub(in crate::fmt) mod glob {
11 pub use super::*;
12}
13
14impl 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
34 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.
43 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.
52 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.
61 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.
70 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
85pub struct Timestamp {
86 time: SystemTime,
87 precision: TimestampPrecision,
88}
89
90impl fmt::Debug for Timestamp {
91 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&mut DebugTuple<'_, '_>.debug_tuple(name:"Timestamp")
102 .field(&TimestampValue(self))
103 .finish()
104 }
105}
106
107impl fmt::Display for Timestamp {
108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109 let formatter: fn(SystemTime) -> Rfc3339Timestamp = 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