#[cfg(feature = "dates")]
use chrono::{DateTime, Duration, NaiveDate, Utc};
#[cfg(feature = "dates")]
pub fn now() -> DateTime<Utc> {
Utc::now()
}
#[cfg(feature = "dates")]
pub fn today() -> NaiveDate {
Utc::now().date_naive()
}
#[cfg(feature = "dates")]
pub fn yesterday() -> NaiveDate {
(Utc::now() - Duration::days(1)).date_naive()
}
#[cfg(feature = "dates")]
pub fn tomorrow() -> NaiveDate {
(Utc::now() + Duration::days(1)).date_naive()
}
#[cfg(feature = "dates")]
pub fn format_date(dt: &DateTime<Utc>, fmt: &str) -> String {
dt.format(fmt).to_string()
}
#[cfg(feature = "dates")]
pub fn parse_date(s: &str, fmt: &str) -> Result<DateTime<Utc>, crate::errors::RokError> {
NaiveDate::parse_from_str(s, fmt)
.map(|d| d.and_hms_opt(0, 0, 0).unwrap().and_utc())
.map_err(|e| crate::errors::RokError::InvalidDate(e.to_string()))
}
#[cfg(feature = "dates")]
pub fn diff_days(a: &NaiveDate, b: &NaiveDate) -> i64 {
(*a - *b).num_days()
}
#[cfg(feature = "dates")]
pub fn human_diff(dt: &DateTime<Utc>) -> String {
let now = Utc::now();
let diff = now.signed_duration_since(*dt);
if diff.num_seconds() < 0 {
let abs = -diff;
if abs.num_days() > 0 {
return format!("in {} days", abs.num_days());
}
if abs.num_hours() > 0 {
return format!("in {} hours", abs.num_hours());
}
if abs.num_minutes() > 0 {
return format!("in {} minutes", abs.num_minutes());
}
return "in a few seconds".to_string();
}
if diff.num_days() > 0 {
return format!("{} days ago", diff.num_days());
}
if diff.num_hours() > 0 {
return format!("{} hours ago", diff.num_hours());
}
if diff.num_minutes() > 0 {
return format!("{} minutes ago", diff.num_minutes());
}
"a few seconds ago".to_string()
}
#[cfg(feature = "dates")]
pub fn add_days(dt: &NaiveDate, days: i64) -> NaiveDate {
*dt + Duration::days(days)
}
#[cfg(feature = "dates")]
pub fn add_hours(dt: &DateTime<Utc>, hours: i64) -> DateTime<Utc> {
*dt + Duration::hours(hours)
}
#[cfg(feature = "dates")]
#[cfg(test)]
mod tests {
use super::*;
use chrono::Datelike;
#[test]
fn test_now() {
let n = now();
assert!(n.timestamp() > 0);
}
#[test]
fn test_today() {
let t = today();
assert!(t.year() > 2020);
}
#[test]
fn test_diff_days() {
let a = NaiveDate::from_ymd_opt(2025, 1, 10).unwrap();
let b = NaiveDate::from_ymd_opt(2025, 1, 5).unwrap();
assert_eq!(diff_days(&a, &b), 5);
}
#[test]
fn test_add_days() {
let d = NaiveDate::from_ymd_opt(2025, 1, 1).unwrap();
let result = add_days(&d, 5);
assert_eq!(result.day(), 6);
}
#[test]
fn test_add_hours() {
let dt = Utc::now();
let result = add_hours(&dt, 24);
assert!(result > dt);
}
}