mingli_contract/
validate.rs1pub fn validate_instant(year: i32, month: u32, day: u32, hour: u32, minute: u32, tz: f64) -> Result<(), String> {
18 if !(1900..=2100).contains(&year) {
19 return Err("year 仅支持 1900–2100".into());
20 }
21 if !(1..=12).contains(&month) {
22 return Err("month 须 1–12".into());
23 }
24 let last = days_in_month(year, month);
27 if !(1..=last).contains(&day) {
28 return Err(format!("{year} 年 {month} 月只有 {last} 天"));
29 }
30 if hour > 23 || minute > 59 {
31 return Err("hour/minute 越界".into());
32 }
33 if !(-12.0..=14.0).contains(&tz) {
35 return Err("tz 须在 −12 到 +14 之间".into());
36 }
37 Ok(())
38}
39
40pub fn validate_query(q: &crate::Query) -> Result<(), String> {
47 validate_instant(q.year, q.month, q.day, q.hour, q.minute, q.tz)?;
48 validate_coords(q.latitude, q.longitude)
49}
50
51#[must_use]
53pub fn days_in_month(year: i32, month: u32) -> u32 {
54 match month {
55 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
56 4 | 6 | 9 | 11 => 30,
57 2 if year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) => 29,
58 2 => 28,
59 _ => 0,
60 }
61}
62
63pub fn validate_coords(latitude: Option<f64>, longitude: Option<f64>) -> Result<(), String> {
69 if let Some(lat) = latitude
70 && !(-90.0..=90.0).contains(&lat)
71 {
72 return Err("latitude 须在 −90 到 90 之间".into());
73 }
74 if let Some(lon) = longitude
75 && !(-180.0..=180.0).contains(&lon)
76 {
77 return Err("longitude 须在 −180 到 180 之间".into());
78 }
79 Ok(())
80}