docs: @Override
    public Timestamp getTimestamp(int i, java.util.Calendar cal) throws SQLException {
      checkResultSet(i);
      if (wasNullFlag) {
        return null;
      }
  
      if (cal == null) {
        cal = getDefaultCalendar();
      }
      int col = i - 1;
      int oid = fields[col].getOID();
      if (isBinary(i)) {
        if (oid == Oid.TIMESTAMPTZ || oid == Oid.TIMESTAMP) {
          boolean hasTimeZone = oid == Oid.TIMESTAMPTZ;
          TimeZone tz = cal.getTimeZone();
          return connection.getTimestampUtils().toTimestampBin(tz, thisRow[col], hasTimeZone);
        } else {
          // JDBC spec says getTimestamp of Time and Date must be supported
          long millis;
          if (oid == Oid.TIME || oid == Oid.TIMETZ) {
            millis = getTime(i, cal).getTime();
          } else if (oid == Oid.DATE) {
            millis = getDate(i, cal).getTime();
          } else {
            throw new PSQLException(
                GT.tr("Cannot convert the column of type {0} to requested type {1}.",
                    Oid.toString(oid), "timestamp"),
                PSQLState.DATA_TYPE_MISMATCH);
          }
          return new Timestamp(millis);
        }
      }
  
      // If this is actually a timestamptz, the server-provided timezone will override
      // the one we pass in, which is the desired behaviour. Otherwise, we'll
      // interpret the timezone-less value in the provided timezone.
      String string = getString(i);
      if (oid == Oid.TIME || oid == Oid.TIMETZ) {
        // If server sends us a TIME, we ensure java counterpart has date of 1970-01-01
        return new Timestamp(connection.getTimestampUtils().toTime(cal, string).getTime());
      }
      return connection.getTimestampUtils().toTimestamp(cal, string);
    }