docs: private ParsedTimestamp parseBackendTimestamp(String str) throws SQLException {
      char[] s = str.toCharArray();
      int slen = s.length;
  
      // This is pretty gross..
      ParsedTimestamp result = new ParsedTimestamp();
  
      // We try to parse these fields in order; all are optional
      // (but some combinations don't make sense, e.g. if you have
      // both date and time then they must be whitespace-separated).
      // At least one of date and time must be present.
  
      // leading whitespace
      // yyyy-mm-dd
      // whitespace
      // hh:mm:ss
      // whitespace
      // timezone in one of the formats: +hh, -hh, +hh:mm, -hh:mm
      // whitespace
      // if date is present, an era specifier: AD or BC
      // trailing whitespace
  
      try {
        int start = skipWhitespace(s, 0); // Skip leading whitespace
        int end = firstNonDigit(s, start);
        int num;
        char sep;
  
        // Possibly read date.
        if (charAt(s, end) == '-') {
          //
          // Date
          //
          result.hasDate = true;
  
          // year
          result.year = number(s, start, end);
          start = end + 1; // Skip '-'
  
          // month
          end = firstNonDigit(s, start);
          result.month = number(s, start, end);
  
          sep = charAt(s, end);
          if (sep != '-') {
            throw new NumberFormatException("Expected date to be dash-separated, got '" + sep + "'");
          }
  
          start = end + 1; // Skip '-'
  
          // day of month
          end = firstNonDigit(s, start);
          result.day = number(s, start, end);
  
          start = skipWhitespace(s, end); // Skip trailing whitespace
        }
  
        // Possibly read time.
        if (Character.isDigit(charAt(s, start))) {
          //
          // Time.
          //
  
          result.hasTime = true;
  
          // Hours
  
          end = firstNonDigit(s, start);
          result.hour = number(s, start, end);
  
          sep = charAt(s, end);
          if (sep != ':') {
            throw new NumberFormatException("Expected time to be colon-separated, got '" + sep + "'");
          }
  
          start = end + 1; // Skip ':'
  
          // minutes
  
          end = firstNonDigit(s, start);
          result.minute = number(s, start, end);
  
          sep = charAt(s, end);
          if (sep != ':') {
            throw new NumberFormatException("Expected time to be colon-separated, got '" + sep + "'");
          }
  
          start = end + 1; // Skip ':'
  
          // seconds
  
          end = firstNonDigit(s, start);
          result.second = number(s, start, end);
          start = end;
  
          // Fractional seconds.
          if (charAt(s, start) == '.') {
            end = firstNonDigit(s, start + 1); // Skip '.'
            num = number(s, start + 1, end);
  
            for (int numlength = (end - (start + 1)); numlength < 9; ++numlength) {
              num *= 10;
            }
  
            result.nanos = num;
            start = end;
          }
  
          start = skipWhitespace(s, start); // Skip trailing whitespace
        }
  
        // Possibly read timezone.
        sep = charAt(s, start);
        if (sep == '-' || sep == '+') {
          int tzsign = (sep == '-') ? -1 : 1;
          int tzhr;
          int tzmin;
          int tzsec;
  
          end = firstNonDigit(s, start + 1); // Skip +/-
          tzhr = number(s, start + 1, end);
          start = end;
  
          sep = charAt(s, start);
          if (sep == ':') {
            end = firstNonDigit(s, start + 1); // Skip ':'
            tzmin = number(s, start + 1, end);
            start = end;
          } else {
            tzmin = 0;
          }
  
          tzsec = 0;
          sep = charAt(s, start);
          if (sep == ':') {
            end = firstNonDigit(s, start + 1); // Skip ':'
            tzsec = number(s, start + 1, end);
            start = end;
          }
  
          // Setting offset does not seem to work correctly in all
          // cases.. So get a fresh calendar for a synthetic timezone
          // instead
          result.tz = getCalendar(tzsign, tzhr, tzmin, tzsec);
  
          start = skipWhitespace(s, start); // Skip trailing whitespace
        }
  
        if (result.hasDate && start < slen) {
          String eraString = new String(s, start, slen - start);
          if (eraString.startsWith("AD")) {
            result.era = GregorianCalendar.AD;
            start += 2;
          } else if (eraString.startsWith("BC")) {
            result.era = GregorianCalendar.BC;
            start += 2;
          }
        }
  
        if (start < slen) {
          throw new NumberFormatException(
              "Trailing junk on timestamp: '" + new String(s, start, slen - start) + "'");
        }
  
        if (!result.hasTime && !result.hasDate) {
          throw new NumberFormatException("Timestamp has neither date nor time");
        }
  
      } catch (NumberFormatException nfe) {
        throw new PSQLException(
            GT.tr("Bad value for type timestamp/date/time: {1}", str),
            PSQLState.BAD_DATETIME_FORMAT, nfe);
      }
  
      return result;
    }