use crate::core::date::BS_EPOCH_YEAR;
use crate::core::error::{NpdatetimeError, Result};
include!(concat!(env!("OUT_DIR"), "/calendar_data.rs"));
fn get_bs_month_data() -> Vec<[u8; 12]> {
let mut result = Vec::new();
let mut current_year = -1;
let mut year_data = [0u8; 12];
for &(year, month, days) in BS_CALENDAR_DATA {
if year != current_year {
if current_year != -1 {
result.push(year_data);
}
current_year = year;
year_data = [0u8; 12];
}
if (1..=12).contains(&month) {
year_data[month as usize - 1] = days;
}
}
result.push(year_data);
result
}
lazy_static::lazy_static! {
static ref BS_MONTH_DATA: Vec<[u8; 12]> = get_bs_month_data();
}
pub fn get_days_in_month(year: i32, month: u8) -> Result<u8> {
let index = (year - BS_EPOCH_YEAR) as usize;
if index >= BS_MONTH_DATA.len() {
return Err(NpdatetimeError::OutOfRange(format!(
"Year {} is out of supported range",
year
)));
}
Ok(BS_MONTH_DATA[index][(month - 1) as usize])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_csv_data_loaded() {
assert!(
!BS_MONTH_DATA.is_empty(),
"BS_MONTH_DATA should not be empty"
);
assert_eq!(BS_MONTH_DATA.len(), 126, "Expected 126 years of data");
}
#[test]
fn test_first_year_data() {
let days = get_days_in_month(1975, 1).unwrap();
assert_eq!(days, 31, "1975 Baisakh should have 31 days");
let days = get_days_in_month(1975, 5).unwrap();
assert_eq!(days, 31, "1975 Bhadra should have 31 days");
let days = get_days_in_month(1975, 12).unwrap();
assert_eq!(days, 30, "1975 Chaitra should have 30 days");
}
#[test]
fn test_known_year_2077() {
assert_eq!(get_days_in_month(2077, 1).unwrap(), 31);
assert_eq!(get_days_in_month(2077, 2).unwrap(), 32);
assert_eq!(get_days_in_month(2077, 5).unwrap(), 31);
assert_eq!(get_days_in_month(2077, 12).unwrap(), 31);
}
#[test]
fn test_last_year_data() {
let days = get_days_in_month(2100, 1).unwrap();
assert_eq!(days, 31, "2100 Baisakh should have 31 days");
let days = get_days_in_month(2100, 12).unwrap();
assert_eq!(days, 30, "2100 Chaitra should have 30 days");
}
#[test]
fn test_month_range_validation() {
for month in 1..=12 {
assert!(get_days_in_month(2077, month).is_ok());
}
}
#[test]
fn test_out_of_range_year_before() {
let result = get_days_in_month(1974, 1);
assert!(result.is_err(), "Year 1974 should be out of range");
}
#[test]
fn test_out_of_range_year_after() {
let result = get_days_in_month(2101, 1);
assert!(result.is_err(), "Year 2101 should be out of range");
}
#[test]
fn test_all_years_all_months() {
for year in 1975..=2100 {
for month in 1..=12 {
let days = get_days_in_month(year, month).unwrap();
assert!(
(29..=32).contains(&days),
"Year {} month {} has invalid day count: {}",
year,
month,
days
);
}
}
}
#[test]
fn test_year_totals_within_range() {
for year in 1975..=2100 {
let total: u32 = (1..=12)
.map(|m| get_days_in_month(year, m).unwrap() as u32)
.sum();
assert!(
(354..=385).contains(&total),
"Year {} has invalid total days: {}",
year,
total
);
}
}
}