///|
/// Accepted date formats have an explicit day/month order and four-digit years.
pub fn date_formats() -> Array[String] {
  ["YYYY-MM-DD", "YYYY/MM/DD", "YYYYMMDD", "DD/MM/YYYY", "MM/DD/YYYY"]
}

///|
fn decimal_at(
  chars : Array[Char],
  a : Int32,
  b : Int32,
) -> Int32 raise LoomError {
  let mut n = 0
  for i in a.. String raise LoomError {
  let c = text.to_array()
  let (year, month, day) = match source {
    "YYYYMMDD" => {
      if c.length() != 8 {
        raise LoomError("date length does not match YYYYMMDD")
      }
      (decimal_at(c, 0, 4), decimal_at(c, 4, 6), decimal_at(c, 6, 8))
    }
    "YYYY-MM-DD" | "YYYY/MM/DD" => {
      let separator = if source == "YYYY-MM-DD" { '-' } else { '/' }
      if c.length() != 10 || c[4] != separator || c[7] != separator {
        raise LoomError("date does not match declared format")
      }
      (decimal_at(c, 0, 4), decimal_at(c, 5, 7), decimal_at(c, 8, 10))
    }
    "DD/MM/YYYY" | "MM/DD/YYYY" => {
      if c.length() != 10 || c[2] != '/' || c[5] != '/' {
        raise LoomError("date does not match declared format")
      }
      let a = decimal_at(c, 0, 2)
      let b = decimal_at(c, 3, 5)
      (
        decimal_at(c, 6, 10),
        if source == "DD/MM/YYYY" {
          b
        } else {
          a
        },
        if source == "DD/MM/YYYY" {
          a
        } else {
          b
        },
      )
    }
    _ => raise LoomError("unsupported source date format")
  }
  if year < 1 || month < 1 || month > 12 {
    raise LoomError("invalid calendar date")
  }
  let leap = year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)
  let days = [
    31,
    if leap {
      29
    } else {
      28
    },
    31,
    30,
    31,
    30,
    31,
    31,
    30,
    31,
    30,
    31,
  ]
  if day < 1 || day > days[month - 1] {
    raise LoomError("invalid calendar date")
  }
  let y = year.to_string().pad_start(4, '0')
  let m = month.to_string().pad_start(2, '0')
  let d = day.to_string().pad_start(2, '0')
  match target {
    "YYYY-MM-DD" => "\{y}-\{m}-\{d}"
    "YYYY/MM/DD" => "\{y}/\{m}/\{d}"
    "YYYYMMDD" => "\{y}\{m}\{d}"
    "DD/MM/YYYY" => "\{d}/\{m}/\{y}"
    "MM/DD/YYYY" => "\{m}/\{d}/\{y}"
    _ => raise LoomError("unsupported target date format")
  }
}