use std::time::{SystemTime, Duration};
fn to_relative_past_time(past: SystemTime) -> String {
let now = SystemTime::now();
// Compute the time difference between `now` and `past`.
// `duration_since()` returns a Result:
// - Ok(d): `now` is after `past`, so the duration is valid.
// - Err(e): `past` is actually in the future (or the clock moved backwards).
// In that case, `e.duration()` gives the absolute difference.
// This ensures `delta` is always a positive Duration.
let delta = match now.duration_since(past) {
Ok(d) => d,
Err(e) => e.duration(),
};
let seconds = delta.as_secs() as i64;
let minutes = seconds / 60;
let hours = seconds / 3600;
let days = seconds / 86400;
if seconds < 60 {
return if seconds == 1 {
"one second ago".to_string()
} else {
format!("{seconds} seconds ago")
};
}
if seconds < 3600 {
return if minutes == 1 {
"a minute ago".to_string()
} else {
format!("{minutes} minutes ago")
};
}
if seconds < 86400 {
return if hours == 1 {
"an hour ago".to_string()
} else {
format!("{hours} hours ago")
};
}
if seconds < 2_592_000 { // 30 days
return if days == 1 {
"yesterday".to_string()
} else {
format!("{days} days ago")
};
}
if seconds < 31_104_000 { // 12 months
let months = days / 30;
return if months <= 1 {
"a month ago".to_string()
} else {
format!("{months} months ago")
};
}
let years = days / 365;
if years <= 1 {
"a year ago".to_string()
} else {
format!("{years} years ago")
}
}
fn test(hours_ago: f64) {
let seconds_ago = (hours_ago * 3600.0).round() as u64;
let past = SystemTime::now() - Duration::from_secs(seconds_ago);
println!("{}", to_relative_past_time(past));
}
fn main() {
test(0.01); // 36 seconds ago
test(0.2); // 12 minutes ago
test(3.0); // 3 hours ago
test(25.0); // yesterday
test(360.0); // 15 days ago
test(1239.0); // a month ago
test(2239.0); // 3 months ago
test(8760.0); // a year ago
test(98763.0); // 11 years ago
}
/*
run:
36 seconds ago
12 minutes ago
3 hours ago
yesterday
15 days ago
a month ago
3 months ago
a year ago
11 years ago
*/