bbc_news_cli/
date_utils.rs1use chrono::{DateTime, Utc};
2
3pub fn humanize_time(date_str: &str) -> String {
6 let parsed = DateTime::parse_from_str(&format!("{} +0000", date_str), "%Y-%m-%d %H:%M:%S %z");
8
9 let date_time = match parsed {
10 Ok(dt) => dt.with_timezone(&Utc),
11 Err(_) => {
12 return date_str.to_string();
14 }
15 };
16
17 let now = Utc::now();
18 let duration = now.signed_duration_since(date_time);
19
20 let seconds = duration.num_seconds();
21 let minutes = duration.num_minutes();
22 let hours = duration.num_hours();
23 let days = duration.num_days();
24
25 if seconds < 0 {
26 return "just now".to_string();
28 } else if seconds < 60 {
29 return "just now".to_string();
30 } else if minutes < 60 {
31 if minutes == 1 {
32 return "1 minute ago".to_string();
33 } else {
34 return format!("{} minutes ago", minutes);
35 }
36 } else if hours < 24 {
37 if hours == 1 {
38 return "1 hour ago".to_string();
39 } else {
40 return format!("{} hours ago", hours);
41 }
42 } else if days == 1 {
43 return "yesterday".to_string();
44 } else if days < 7 {
45 return format!("{} days ago", days);
46 } else if days < 30 {
47 let weeks = days / 7;
48 if weeks == 1 {
49 return "1 week ago".to_string();
50 } else {
51 return format!("{} weeks ago", weeks);
52 }
53 } else if days < 365 {
54 let months = days / 30;
55 if months == 1 {
56 return "1 month ago".to_string();
57 } else {
58 return format!("{} months ago", months);
59 }
60 } else {
61 let years = days / 365;
62 if years == 1 {
63 return "1 year ago".to_string();
64 } else {
65 return format!("{} years ago", years);
66 }
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use chrono::Duration;
74
75 #[test]
76 fn test_humanize_recent() {
77 let now = Utc::now();
78
79 let recent = (now - Duration::seconds(30)).format("%Y-%m-%d %H:%M:%S").to_string();
81 assert_eq!(humanize_time(&recent), "just now");
82
83 let mins = (now - Duration::minutes(5)).format("%Y-%m-%d %H:%M:%S").to_string();
85 assert_eq!(humanize_time(&mins), "5 minutes ago");
86 }
87
88 #[test]
89 fn test_humanize_hours() {
90 let now = Utc::now();
91 let hours = (now - Duration::hours(3)).format("%Y-%m-%d %H:%M:%S").to_string();
92 assert_eq!(humanize_time(&hours), "3 hours ago");
93 }
94
95 #[test]
96 fn test_humanize_days() {
97 let now = Utc::now();
98 let yesterday = (now - Duration::days(1)).format("%Y-%m-%d %H:%M:%S").to_string();
99 assert_eq!(humanize_time(&yesterday), "yesterday");
100
101 let days = (now - Duration::days(5)).format("%Y-%m-%d %H:%M:%S").to_string();
102 assert_eq!(humanize_time(&days), "5 days ago");
103 }
104
105 #[test]
106 fn test_invalid_date() {
107 let invalid = "invalid date";
108 assert_eq!(humanize_time(invalid), "invalid date");
109 }
110}