1pub fn parse(s: &str) -> Option<i64> {
5 let b = s.as_bytes();
6 if b.len() < 19
7 || b[4] != b'-'
8 || b[7] != b'-'
9 || b[10] != b'T'
10 || b[13] != b':'
11 || b[16] != b':'
12 {
13 return None;
14 }
15 let n = |r: std::ops::Range<usize>| s.get(r)?.parse::<i64>().ok();
16 let (y, m, d) = (n(0..4)?, n(5..7)?, n(8..10)?);
17 let (hh, mm, ss) = (n(11..13)?, n(14..16)?, n(17..19)?);
18 if !(1..=12).contains(&m) || !(1..=31).contains(&d) {
19 return None;
20 }
21 let y = if m <= 2 { y - 1 } else { y };
23 let era = y.div_euclid(400);
24 let yoe = y - era * 400;
25 let doy = (153 * (if m > 2 { m - 3 } else { m + 9 }) + 2) / 5 + d - 1;
26 let doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
27 let days = era * 146097 + doe - 719468;
28 Some(days * 86400 + hh * 3600 + mm * 60 + ss)
29}