use chrono::{DateTime, TimeDelta, Utc};
pub fn is_not_before_valid(
now: DateTime<Utc>,
not_before: DateTime<Utc>,
clock_skew_seconds: u64,
) -> bool {
let skew = TimeDelta::seconds(clock_skew_seconds as i64);
now + skew >= not_before
}
pub fn is_not_on_or_after_valid(
now: DateTime<Utc>,
not_on_or_after: DateTime<Utc>,
clock_skew_seconds: u64,
) -> bool {
let skew = TimeDelta::seconds(clock_skew_seconds as i64);
now - skew < not_on_or_after
}
pub fn is_within_age_limit(
now: DateTime<Utc>,
timestamp: DateTime<Utc>,
max_age_seconds: u64,
) -> bool {
let age = now.signed_duration_since(timestamp);
if age.num_seconds() < 0 {
return true;
}
age.num_seconds() as u64 <= max_age_seconds
}
pub fn time_difference_seconds(a: DateTime<Utc>, b: DateTime<Utc>) -> i64 {
a.signed_duration_since(b).num_seconds().abs()
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::TimeDelta;
#[test]
fn test_not_before_valid_current_time() {
let now = Utc::now();
let not_before = now - TimeDelta::seconds(60);
assert!(is_not_before_valid(now, not_before, 180));
}
#[test]
fn test_not_before_valid_with_skew() {
let now = Utc::now();
let not_before = now + TimeDelta::seconds(120);
assert!(is_not_before_valid(now, not_before, 180));
}
#[test]
fn test_not_before_invalid_beyond_skew() {
let now = Utc::now();
let not_before = now + TimeDelta::seconds(300);
assert!(!is_not_before_valid(now, not_before, 180));
}
#[test]
fn test_not_on_or_after_valid_current_time() {
let now = Utc::now();
let not_on_or_after = now + TimeDelta::seconds(60);
assert!(is_not_on_or_after_valid(now, not_on_or_after, 180));
}
#[test]
fn test_not_on_or_after_valid_with_skew() {
let now = Utc::now();
let not_on_or_after = now - TimeDelta::seconds(120);
assert!(is_not_on_or_after_valid(now, not_on_or_after, 180));
}
#[test]
fn test_not_on_or_after_invalid_beyond_skew() {
let now = Utc::now();
let not_on_or_after = now - TimeDelta::seconds(300);
assert!(!is_not_on_or_after_valid(now, not_on_or_after, 180));
}
#[test]
fn test_not_on_or_after_exact_boundary() {
let now = Utc::now();
let not_on_or_after = now - TimeDelta::seconds(179);
assert!(is_not_on_or_after_valid(now, not_on_or_after, 180));
}
#[test]
fn test_within_age_limit() {
let now = Utc::now();
let timestamp = now - TimeDelta::seconds(60);
assert!(is_within_age_limit(now, timestamp, 300));
}
#[test]
fn test_beyond_age_limit() {
let now = Utc::now();
let timestamp = now - TimeDelta::seconds(600);
assert!(!is_within_age_limit(now, timestamp, 300));
}
#[test]
fn test_future_timestamp_within_age() {
let now = Utc::now();
let timestamp = now + TimeDelta::seconds(10);
assert!(is_within_age_limit(now, timestamp, 300));
}
#[test]
fn test_time_difference_seconds() {
let a = Utc::now();
let b = a - TimeDelta::seconds(120);
assert_eq!(time_difference_seconds(a, b), 120);
assert_eq!(time_difference_seconds(b, a), 120); }
#[test]
fn test_zero_skew() {
let now = Utc::now();
let not_before = now - TimeDelta::seconds(1);
assert!(is_not_before_valid(now, not_before, 0));
let not_before_future = now + TimeDelta::seconds(1);
assert!(!is_not_before_valid(now, not_before_future, 0));
}
}