use rand::Rng;
use std::time::Duration;
pub(super) const SLOT_JITTER_SECS: u64 = 15 * 60;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct PostingSlot {
pub(super) hour: u8,
pub(super) minute: u8,
}
impl PostingSlot {
pub fn parse(s: &str) -> Option<Self> {
let parts: Vec<&str> = s.split(':').collect();
if parts.len() != 2 {
return None;
}
let hour: u8 = parts[0].parse().ok()?;
let minute: u8 = parts[1].parse().ok()?;
if hour > 23 || minute > 59 {
return None;
}
Some(Self { hour, minute })
}
pub fn as_minutes(&self) -> u32 {
self.hour as u32 * 60 + self.minute as u32
}
pub fn format(&self) -> String {
format!("{:02}:{:02}", self.hour, self.minute)
}
pub fn to_naive_time(&self) -> chrono::NaiveTime {
chrono::NaiveTime::from_hms_opt(self.hour as u32, self.minute as u32, 0)
.expect("PostingSlot values are validated on construction")
}
}
pub fn apply_slot_jitter(wait: Duration) -> Duration {
let jitter_secs = rand::rng().random_range(0..=SLOT_JITTER_SECS * 2);
let wait_secs = wait.as_secs() as i64 + jitter_secs as i64 - SLOT_JITTER_SECS as i64;
Duration::from_secs(wait_secs.max(0) as u64)
}