///|
/// ISO Gregorian date input, years 0001..9999. Editing accepts partial dates;
/// completed invalid dates remain visible with Invalid status.
pub fn iso_date() -> Mask {
let mask = pattern("####-##-##").unwrap()
match mask.kind {
PatternKind(p) => { kind: DateKind(p), }
_ => abort("internal date pattern")
}
}
///|
fn date_status(raw : Array[Char]) -> Status {
if raw.is_empty() {
return Empty
}
if raw.length() < 8 {
return Incomplete
}
let mut year = 0
for i in 0..<4 {
year = year * 10 + raw[i].to_int() - 48
}
let month = (raw[4].to_int() - 48) * 10 + raw[5].to_int() - 48
let day = (raw[6].to_int() - 48) * 10 + raw[7].to_int() - 48
if year == 0 {
return Invalid("year must be between 0001 and 9999")
}
if month < 1 || month > 12 {
return Invalid("month must be between 01 and 12")
}
let leap = year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)
let days = match month {
2 => if leap { 29 } else { 28 }
4 | 6 | 9 | 11 => 30
_ => 31
}
if day < 1 || day > days {
return Invalid("day is outside this month")
}
Complete
}