use crate::common::print_formatted_error::print_formatted_error;
use chrono::{DateTime, Duration, NaiveDateTime, Utc};
use termimad::crossterm::style::{StyledContent, Stylize};
pub fn format_relative_time(date_str: &str) -> Result<StyledContent<String>, chrono::ParseError> {
let date = match DateTime::parse_from_rfc3339(date_str)
.map(|dt| dt.naive_utc())
.or_else(|_| {
let format = "%Y-%m-%d %H:%M:%S%.6f UTC";
NaiveDateTime::parse_from_str(date_str, format)
}) {
Ok(formatted_data) => formatted_data,
Err(_) => {
print_formatted_error("Invalid data format.");
std::process::exit(1);
}
};
let now = Utc::now().naive_utc();
let duration = now.signed_duration_since(date);
if duration.num_seconds() < 60 {
return Ok("just now".to_string().green());
}
if duration.num_minutes() < 60 {
return Ok(format!(
"{} minute{} ago",
duration.num_minutes(),
if duration.num_minutes() == 1 { "" } else { "s" }
)
.green());
}
if duration.num_hours() < 24 {
return Ok(format!(
"{} hour{} ago",
duration.num_hours(),
if duration.num_hours() == 1 { "" } else { "s" }
)
.green());
}
if duration.num_days() <= 7 {
return Ok(format!(
"{} day{} ago",
duration.num_days(),
if duration.num_days() == 1 { "" } else { "s" }
)
.green());
}
if duration.num_days() < 30 {
return Ok(format!(
"{} day{} ago",
duration.num_days(),
if duration.num_days() == 1 { "" } else { "s" }
)
.yellow());
}
if duration < Duration::days(365) {
let months = duration.num_days() / 30;
return Ok(format!("{} month{} ago", months, if months == 1 { "" } else { "s" }).red());
}
let years = duration.num_days() / 365;
Ok(format!("{} year{} ago", years, if years == 1 { "" } else { "s" }).red())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_relative_time_format() {
let now = Utc::now().to_rfc3339();
assert_eq!(
format_relative_time(&now).unwrap(),
"just now".to_string().green()
);
let an_hour_ago = (Utc::now() - Duration::hours(1)).to_rfc3339();
assert_eq!(
format_relative_time(&an_hour_ago).unwrap(),
"1 hour ago".to_string().green()
);
let three_days_ago = (Utc::now() - Duration::days(3)).to_rfc3339();
assert_eq!(
format_relative_time(&three_days_ago).unwrap(),
"3 days ago".to_string().green()
);
}
}