use std::thread;
use std::time::Duration;
use anyhow::{Context, Result};
pub use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, Utc};
#[must_use]
pub fn now() -> DateTime<Utc> {
Utc::now()
}
#[must_use]
pub fn now_local() -> DateTime<Local> {
Local::now()
}
pub fn parse<S: AsRef<str>>(s: S, fmt: &str) -> Result<NaiveDateTime> {
let s = s.as_ref();
NaiveDateTime::parse_from_str(s, fmt)
.with_context(|| format!("Failed to parse datetime '{s}' with format '{fmt}'"))
}
#[must_use]
pub fn format<T: chrono::TimeZone>(dt: &DateTime<T>, fmt: &str) -> String
where
T::Offset: std::fmt::Display,
{
dt.format(fmt).to_string()
}
pub fn sleep_secs(secs: u64) {
thread::sleep(Duration::from_secs(secs));
}
pub fn sleep_millis(millis: u64) {
thread::sleep(Duration::from_millis(millis));
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::{Datelike, Timelike};
#[test]
fn now_returns_current_time() {
let time = now();
assert!(time.year() >= 2020);
}
#[test]
fn now_local_returns_local_time() {
let time = now_local();
assert!(time.year() >= 2020);
}
#[test]
fn parse_parses_datetime() {
let dt = parse("2024-01-15 14:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
assert_eq!(dt.year(), 2024);
assert_eq!(dt.month(), 1);
assert_eq!(dt.day(), 15);
assert_eq!(dt.hour(), 14);
assert_eq!(dt.minute(), 30);
assert_eq!(dt.second(), 0);
}
#[test]
fn parse_fails_on_invalid_format() {
let result = parse("2024-01-15", "%Y-%m-%d %H:%M:%S");
assert!(result.is_err());
}
#[test]
fn format_formats_datetime() {
let dt = parse("2024-01-15 14:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
let dt_utc = DateTime::<Utc>::from_naive_utc_and_offset(dt, Utc);
let formatted = format(&dt_utc, "%Y/%m/%d");
assert_eq!(formatted, "2024/01/15");
}
#[test]
fn format_supports_various_patterns() {
let dt = parse("2024-01-15 14:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
let dt_utc = DateTime::<Utc>::from_naive_utc_and_offset(dt, Utc);
assert_eq!(format(&dt_utc, "%Y"), "2024");
assert_eq!(format(&dt_utc, "%m"), "01");
assert_eq!(format(&dt_utc, "%d"), "15");
assert_eq!(format(&dt_utc, "%H:%M"), "14:30");
}
#[test]
fn sleep_secs_sleeps() {
use std::time::Instant;
let start = Instant::now();
sleep_secs(0); let elapsed = start.elapsed();
assert!(elapsed.as_millis() < 100);
}
#[test]
fn sleep_millis_sleeps() {
use std::time::Instant;
let start = Instant::now();
sleep_millis(10);
let elapsed = start.elapsed();
assert!(elapsed.as_millis() >= 10);
assert!(elapsed.as_millis() < 100);
}
}