basic_human_duration/
lib.rs1use std::fmt;
2use time::Duration;
3
4pub trait ChronoHumanDuration {
5 type Displayer: fmt::Display;
6 fn format_human(&self) -> Self::Displayer;
7}
8
9impl ChronoHumanDuration for Duration {
10 type Displayer = Displayer;
11 fn format_human(&self) -> Self::Displayer {
12 Displayer { d: *self }
13 }
14}
15
16pub struct Displayer {
17 d: Duration,
18}
19
20impl fmt::Display for Displayer {
21 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22 let mut wrote = false;
23 let d = self.d;
24
25 let months = d.whole_weeks() / 4;
26 if months > 0 {
27 write!(f, "{} month{}", months, if months > 1 { "s" } else { "" })?;
28 wrote = true;
29 } else {
30 let weeks = d.whole_weeks();
31 if weeks > 0 {
32 write!(
33 f,
34 "{}{} week{}",
35 if wrote { ", " } else { "" },
36 weeks,
37 if weeks > 1 { "s" } else { "" }
38 )?;
39 wrote = true;
40 } else {
41 let days = d.whole_days();
42 if days > 0 {
43 write!(
44 f,
45 "{}{} day{}",
46 if wrote { ", " } else { "" },
47 days,
48 if days > 1 { "s" } else { "" }
49 )?;
50 wrote = true;
51 } else {
52 let hours = d.whole_hours();
53 if hours > 0 {
54 write!(
55 f,
56 "{}{} hour{}",
57 if wrote { ", " } else { "" },
58 hours,
59 if hours > 1 { "s" } else { "" }
60 )?;
61 wrote = true;
62 } else {
63 let minutes = d.whole_minutes();
64 if minutes > 0 {
65 write!(
66 f,
67 "{}{} minute{}",
68 if wrote { ", " } else { "" },
69 minutes,
70 if minutes > 1 { "s" } else { "" }
71 )?;
72 wrote = true;
73 }
74 }
75 }
76 }
77 }
78
79 if wrote {
80 write!(f, " ago")
81 } else {
82 write!(f, "just now")
83 }
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use time::Duration;
90 use crate::ChronoHumanDuration;
91
92 #[test]
93 fn it_works() {
94 let d = Duration::weeks(2) + Duration::days(3) + Duration::hours(2) + Duration::minutes(20);
95 assert_eq!(d.format_human().to_string(), "2 weeks ago");
96 let d = Duration::weeks(1);
97 assert_eq!(d.format_human().to_string(), "1 week ago");
98 let d = Duration::days(2) + Duration::hours(2);
99 assert_eq!(d.format_human().to_string(), "2 days ago");
100 let d = Duration::days(1);
101 assert_eq!(d.format_human().to_string(), "1 day ago");
102 let d = Duration::hours(2);
103 assert_eq!(d.format_human().to_string(), "2 hours ago");
104 let d = Duration::hours(1);
105 assert_eq!(d.format_human().to_string(), "1 hour ago");
106 let d = Duration::minutes(2);
107 assert_eq!(d.format_human().to_string(), "2 minutes ago");
108 let d = Duration::minutes(1);
109 assert_eq!(d.format_human().to_string(), "1 minute ago");
110 let d = Duration::seconds(60);
111 assert_eq!(d.format_human().to_string(), "1 minute ago");
112 let d = Duration::seconds(59);
113 assert_eq!(d.format_human().to_string(), "just now");
114 let d = Duration::seconds(1);
115 assert_eq!(d.format_human().to_string(), "just now");
116 }
117}