1use crate::core::date::BS_EPOCH_YEAR;
5use crate::core::error::{NpdatetimeError, Result};
6
7include!(concat!(env!("OUT_DIR"), "/calendar_data.rs"));
9
10fn get_bs_month_data() -> Vec<[u8; 12]> {
12 let mut result = Vec::new();
13 let mut current_year = -1;
14 let mut year_data = [0u8; 12];
15
16 for &(year, month, days) in BS_CALENDAR_DATA {
17 if year != current_year {
18 if current_year != -1 {
19 result.push(year_data);
20 }
21 current_year = year;
22 year_data = [0u8; 12];
23 }
24 if (1..=12).contains(&month) {
25 year_data[month as usize - 1] = days;
26 }
27 }
28 result.push(year_data);
29 result
30}
31
32lazy_static::lazy_static! {
33 static ref BS_MONTH_DATA: Vec<[u8; 12]> = get_bs_month_data();
34}
35
36pub fn get_days_in_month(year: i32, month: u8) -> Result<u8> {
38 let index = (year - BS_EPOCH_YEAR) as usize;
39 if index >= BS_MONTH_DATA.len() {
40 return Err(NpdatetimeError::OutOfRange(format!(
41 "Year {} is out of supported range",
42 year
43 )));
44 }
45
46 Ok(BS_MONTH_DATA[index][(month - 1) as usize])
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn test_csv_data_loaded() {
55 assert!(
57 !BS_MONTH_DATA.is_empty(),
58 "BS_MONTH_DATA should not be empty"
59 );
60 assert_eq!(BS_MONTH_DATA.len(), 126, "Expected 126 years of data");
61 }
62
63 #[test]
64 fn test_first_year_data() {
65 let days = get_days_in_month(1975, 1).unwrap();
67 assert_eq!(days, 31, "1975 Baisakh should have 31 days");
68
69 let days = get_days_in_month(1975, 5).unwrap();
70 assert_eq!(days, 31, "1975 Bhadra should have 31 days");
71
72 let days = get_days_in_month(1975, 12).unwrap();
73 assert_eq!(days, 30, "1975 Chaitra should have 30 days");
74 }
75
76 #[test]
77 fn test_known_year_2077() {
78 assert_eq!(get_days_in_month(2077, 1).unwrap(), 31);
80 assert_eq!(get_days_in_month(2077, 2).unwrap(), 32);
81 assert_eq!(get_days_in_month(2077, 5).unwrap(), 31);
82 assert_eq!(get_days_in_month(2077, 12).unwrap(), 31);
83 }
84
85 #[test]
86 fn test_last_year_data() {
87 let days = get_days_in_month(2100, 1).unwrap();
89 assert_eq!(days, 31, "2100 Baisakh should have 31 days");
90
91 let days = get_days_in_month(2100, 12).unwrap();
92 assert_eq!(days, 30, "2100 Chaitra should have 30 days");
93 }
94
95 #[test]
96 fn test_month_range_validation() {
97 for month in 1..=12 {
99 assert!(get_days_in_month(2077, month).is_ok());
100 }
101 }
102
103 #[test]
104 fn test_out_of_range_year_before() {
105 let result = get_days_in_month(1974, 1);
106 assert!(result.is_err(), "Year 1974 should be out of range");
107 }
108
109 #[test]
110 fn test_out_of_range_year_after() {
111 let result = get_days_in_month(2101, 1);
112 assert!(result.is_err(), "Year 2101 should be out of range");
113 }
114
115 #[test]
116 fn test_all_years_all_months() {
117 for year in 1975..=2100 {
119 for month in 1..=12 {
120 let days = get_days_in_month(year, month).unwrap();
121 assert!(
122 (29..=32).contains(&days),
123 "Year {} month {} has invalid day count: {}",
124 year,
125 month,
126 days
127 );
128 }
129 }
130 }
131
132 #[test]
133 fn test_year_totals_within_range() {
134 for year in 1975..=2100 {
136 let total: u32 = (1..=12)
137 .map(|m| get_days_in_month(year, m).unwrap() as u32)
138 .sum();
139 assert!(
140 (354..=385).contains(&total),
141 "Year {} has invalid total days: {}",
142 year,
143 total
144 );
145 }
146 }
147}