Skip to main content

seedfaker_core/
tz.rs

1/// Parse timezone offset string into total minutes.
2/// Accepts: "Z", "+HHMM", "-HHMM", "+HH:MM", "-HH:MM"
3pub fn parse(s: &str) -> Result<i32, String> {
4    if s == "Z" || s == "z" {
5        return Ok(0);
6    }
7
8    let sign = match s.as_bytes().first() {
9        Some(b'+') => 1,
10        Some(b'-') => -1,
11        _ => return Err(format!("invalid timezone offset '{s}'; expected +HHMM, -HH:MM, or Z")),
12    };
13
14    let body = &s[1..];
15    let (hours, minutes) = if body.len() == 4 && body.is_ascii() {
16        let h = body[..2].parse::<i32>().map_err(|_| format!("invalid timezone offset '{s}'"))?;
17        let m = body[2..].parse::<i32>().map_err(|_| format!("invalid timezone offset '{s}'"))?;
18        (h, m)
19    } else if body.len() == 5 && body.as_bytes()[2] == b':' {
20        let h = body[..2].parse::<i32>().map_err(|_| format!("invalid timezone offset '{s}'"))?;
21        let m = body[3..].parse::<i32>().map_err(|_| format!("invalid timezone offset '{s}'"))?;
22        (h, m)
23    } else {
24        return Err(format!("invalid timezone offset '{s}'; expected +HHMM, -HH:MM, or Z"));
25    };
26
27    if hours > 99 {
28        return Err(format!("invalid timezone offset '{s}'; hours must be 00-99"));
29    }
30    if minutes > 59 {
31        return Err(format!("invalid timezone offset '{s}'; minutes must be 00-59"));
32    }
33
34    Ok(sign * (hours * 60 + minutes))
35}