docs: public static Date parse(String str, boolean strict) {
      if (str != null) str = str.trim();
      if (str == null || str.isEmpty()) throw new IllegalArgumentException("String must be non-empty");
  
      Input s = new Input(str);
      boolean yrNeg = s.getChar() == '-';
      if (yrNeg) s.index++;
      
      int year = parseField("year", s, DATE_SEP, 4, 0, strict);
      // Always validate the year, or it won't fit in a long.
      if (year > MAX_YEAR) throw new ArithmeticException("The given year (" + (yrNeg ? "-" : "") + year + ") exceeds the limit for java.util.Date");
      if (yrNeg) year = -year;
      
      int month = parseField("month", s, DATE_SEP, 2, 2, strict);
      // Always validate the month
      if (month < FIRST_MONTH || month > LAST_MONTH) throw new DateFormatException("month out of range [1..12]", s.str, s.index - 2);
      
      int day = parseField("day", s, DATE_TIME_SEP, 2, 2, strict);
      if (strict && (day < 0 || day > daysInMonth(year, month))) throw new DateFormatException("day out of range [1.." + daysInMonth(year, month) + "]", s.str, s.index - 2);
      
      int hour = parseField("hour", s, TIME_SEP, 2, 2, strict);
      if (strict && hour > 24) throw new DateFormatException("hour out of range [0..24]", s.str, s.index - 2);
      
      int min = parseField("minute", s, TIME_SEP, 2, 2, strict);
      if (strict && min > 59) throw new DateFormatException("minutes out of range [0..59]", s.str, s.index - 2);
      
      int sec = parseField("second", s, null, 2, 2, strict);
      if (strict && sec > 59) throw new DateFormatException("seconds out of range [0..59]", s.str, s.index - 1);
      
      int millis = parseMillis(s);
      if (strict && hour == 24 && (min > 0 || sec > 0 || millis > 0)) {
        throw new DateFormatException("midnight indicator may not include non-zero minutes or seconds", s.str, s.index - 1);
      }
      
      Integer tzOffsetMs = parseTzOffsetMs(s, strict);
      boolean local = tzOffsetMs == null;
      if (local) tzOffsetMs = 0;
      if (strict && s.index < s.len) throw new DateFormatException("unexpected content, expected EOF", s.str, s.index);
      
      // Calculate the number of days elapsed between the epoch and the start of this day.
      long da = elapsedDays(year);
      for (int m = FIRST_MONTH; m < month; m++) {
        da += daysInMonth(year, m);
      }
      da += (day - 1);
      
      // Calculate the number of milliseconds elapsed between the epoch and the given time, accounting for timezone offset.
      long ms = da * MS_IN_DAY + hour * MS_IN_HOUR + min * MS_IN_MIN + sec * MS_IN_SEC + millis - tzOffsetMs;
      
      // Translate from ISO-8601 epoch to Java Date epoch.
      if (ms < (Long.MIN_VALUE + EPOCH_OFFSET_MS)) throw new ArithmeticException("The specified date will not fit into java.util.Date: " + str);
      ms -= EPOCH_OFFSET_MS;
      
      // Handle local timezone.
      if (local) {
        tzOffsetMs = LOCAL_TZ.getOffset(ms);
        if (tzOffsetMs > 0 && ms < (Long.MIN_VALUE + tzOffsetMs)) throw new ArithmeticException("The specified date will not fit into java.util.Date: " + str);
        ms -= tzOffsetMs;
      }
      
      return new Date(ms);
    }