simple-datetime-rs 0.3.0

A high-performance, lightweight date and time library for Rust with dramatically faster parsing, memory-efficient operations, and chrono-compatible formatting
Documentation
use crate::constants::MONTH_DAYS;

#[inline]
pub fn next_leap_year(year: u64) -> u64 {
    recent_leap_year(year + 4)
}
#[inline]
pub fn recent_leap_year(year: u64) -> u64 {
    year - (year % 4)
}
#[inline]
pub fn leap_year(year: u64) -> bool {
    (year & 3) == 0 && (year % 100 != 0 || year % 400 == 0)
}
#[inline]
pub fn month_index(month: u64) -> usize {
    (month.saturating_sub(1)) as usize
}

pub fn month_days(month: u64, leap_year: bool) -> u64 {
    if leap_year && month == 2 {
        return MONTH_DAYS[month_index(month)] + 1;
    }
    MONTH_DAYS[month_index(month)]
}
#[inline]
pub fn before_leap(month: u64) -> bool {
    month < 3
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_date_leap_year() {
        assert!(leap_year(2020));
        assert!(!leap_year(2018));
        assert!(leap_year(2016));
    }

    #[test]
    fn test_date_recent_leap_year() {
        assert_eq!(recent_leap_year(2020), 2020);
        assert_eq!(recent_leap_year(2019), 2016);
    }

    #[test]
    fn test_date_next_leap_year() {
        assert_eq!(next_leap_year(2020), 2024);
        assert_eq!(next_leap_year(2019), 2020);
    }

    #[test]
    fn test_month_days() {
        assert_eq!(month_days(1, false), 31); // January
        assert_eq!(month_days(3, false), 31); // March
        assert_eq!(month_days(4, false), 30); // April
        assert_eq!(month_days(6, false), 30); // June
        assert_eq!(month_days(9, false), 30); // September
        assert_eq!(month_days(11, false), 30); // November
        assert_eq!(month_days(12, false), 31); // December

        assert_eq!(month_days(2, false), 28);

        assert_eq!(month_days(2, true), 29);

        for month in 1..=12 {
            if month != 2 {
                assert_eq!(month_days(month, true), month_days(month, false));
            }
        }
    }

    #[test]
    fn test_before_leap() {
        assert!(before_leap(1)); // January
        assert!(before_leap(2)); // February
        assert!(!before_leap(3)); // March
        assert!(!before_leap(4)); // April
        assert!(!before_leap(12)); // December
    }

    #[test]
    fn test_month_index() {
        assert_eq!(month_index(1), 0);
        assert_eq!(month_index(6), 5);
        assert_eq!(month_index(12), 11);
    }

    #[test]
    fn test_leap_year_edge_cases() {
        assert!(leap_year(2000)); // Divisible by 400
        assert!(!leap_year(1900)); // Divisible by 100 but not 400
        assert!(!leap_year(1800)); // Divisible by 100 but not 400
        assert!(!leap_year(1700)); // Divisible by 100 but not 400

        assert!(leap_year(2004)); // Divisible by 4
        assert!(leap_year(2008)); // Divisible by 4
        assert!(!leap_year(2001)); // Not divisible by 4
        assert!(!leap_year(2002)); // Not divisible by 4
        assert!(!leap_year(2003)); // Not divisible by 4
    }

    #[test]
    fn test_recent_leap_year_edge_cases() {
        assert_eq!(recent_leap_year(2020), 2020); // Already a leap year
        assert_eq!(recent_leap_year(2021), 2020); // Previous leap year
        assert_eq!(recent_leap_year(2022), 2020); // Previous leap year
        assert_eq!(recent_leap_year(2023), 2020); // Previous leap year
        assert_eq!(recent_leap_year(2024), 2024); // Next leap year
    }

    #[test]
    fn test_next_leap_year_edge_cases() {
        assert_eq!(next_leap_year(2020), 2024); // Current leap year
        assert_eq!(next_leap_year(2021), 2024); // Next leap year
        assert_eq!(next_leap_year(2022), 2024); // Next leap year
        assert_eq!(next_leap_year(2023), 2024); // Next leap year
        assert_eq!(next_leap_year(2024), 2028); // Next leap year after current
    }
}