use time::{format_description::StaticFormatDescription, macros::format_description, Duration};
use crate::config::LogRotation;
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Rotation(pub LogRotation);
impl Rotation {
pub const MINUTELY: Self = Self(LogRotation::Minutely);
pub const HOURLY: Self = Self(LogRotation::Hourly);
pub const DAILY: Self = Self(LogRotation::Daily);
pub const NEVER: Self = Self(LogRotation::Never);
pub(super) fn next_date(
&self,
current_date: &time::OffsetDateTime,
) -> Option<time::OffsetDateTime> {
let unrounded_next_date = match *self {
Rotation::MINUTELY => *current_date + Duration::minutes(1),
Rotation::HOURLY => *current_date + Duration::hours(1),
Rotation::DAILY => *current_date + Duration::days(1),
Rotation::NEVER => return None,
};
Some(self.round_date(&unrounded_next_date))
}
pub(super) fn round_date(&self, date: &time::OffsetDateTime) -> time::OffsetDateTime {
match *self {
Rotation::MINUTELY => date.truncate_to_minute(),
Rotation::HOURLY => date.truncate_to_hour(),
Rotation::DAILY => date.truncate_to_day(),
Rotation::NEVER => *date,
}
}
pub(super) fn date_format(&self) -> StaticFormatDescription {
match *self {
Rotation::MINUTELY => {
format_description!(version = 1, "[year]-[month]-[day]-[hour]-[minute]")
}
Rotation::HOURLY => format_description!(version = 1, "[year]-[month]-[day]-[hour]"),
Rotation::DAILY => format_description!(version = 1, "[year]-[month]-[day]"),
Rotation::NEVER => &[],
}
}
}
#[cfg(test)]
mod tests {
use super::Rotation;
fn sample_date() -> time::OffsetDateTime {
time::OffsetDateTime::from_unix_timestamp_nanos(1_792_078_245_123_000_000).unwrap()
}
fn suffix(rotation: &Rotation, date: time::OffsetDateTime) -> String {
date.format(rotation.date_format()).unwrap()
}
#[test]
fn test_rotation_round_date() {
let date = sample_date();
assert_eq!(
Rotation::MINUTELY.round_date(&date).unix_timestamp_nanos(),
1_792_078_200_000_000_000
);
assert_eq!(
Rotation::HOURLY.round_date(&date).unix_timestamp_nanos(),
1_792_076_400_000_000_000
);
assert_eq!(
Rotation::DAILY.round_date(&date).unix_timestamp_nanos(),
1_792_022_400_000_000_000
);
}
#[test]
fn test_rotation_date_format() {
let date = sample_date();
assert_eq!(suffix(&Rotation::MINUTELY, date), "2026-10-15-15-30");
assert_eq!(suffix(&Rotation::HOURLY, date), "2026-10-15-15");
assert_eq!(suffix(&Rotation::DAILY, date), "2026-10-15");
assert_eq!(suffix(&Rotation::NEVER, date), "");
}
}