use chrono::prelude::*; use mlua::{ prelude::*, LuaSerdeExt, }; // Taken from https://github.com/chronotope/chrono/issues/69#issuecomment-1510506428 trait NaiveDateExt { fn days_in_month(&self) -> u32; fn days_in_year(&self) -> u32; fn is_leap_year(&self) -> bool; } impl NaiveDateExt for NaiveDate { fn days_in_month(&self) -> u32 { let month = self.month(); match month { 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31, 4 | 6 | 9 | 11 => 30, 2 => { if self.is_leap_year() { 29 } else { 28 } } _ => panic!("Invalid month: {}", month), } } fn days_in_year(&self) -> u32 { if self.is_leap_year() { 366 } else { 365 } } fn is_leap_year(&self) -> bool { let year = self.year(); return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); } } struct Day { day: u32, ce: bool, weekday: Weekday, } pub fn get_calendar_table(lua: &Lua, (year, month, day): (i32, u32, u32)) -> LuaResult { let date = NaiveDate::from_ymd_opt(year, month, day).ok_or(LuaError::external("invalid date"))?; let days: Vec = (1..=date.days_in_month()) .map(|day| NaiveDate::from_ymd_opt(date.year(), date.month(), day).unwrap()) .map(|date| { let (ce, year) = date.year_ce(); Day { day: date.day(), ce, weekday: date.weekday(), } }) .collect(); let calendar: Vec> = vec![vec![], vec![], vec![], vec![], vec![], vec![], vec![]]; if days[1].weekday != Weekday::Mon { get_calendar_table(lua) } if days.last().unwrap().weekday != Weekday::Sun {} Ok(lua.create_table()?) }