docs: public Timestamp getInternalTimestamp(ColumnInformation columnInfo, Calendar userCalendar,
        TimeZone timeZone) throws SQLException {
      if (lastValueWasNull()) {
        return null;
      }
  
      switch (columnInfo.getColumnType()) {
        case TIMESTAMP:
        case DATETIME:
        case DATE:
        case VARCHAR:
        case VARSTRING:
        case STRING:
  
          int nanoBegin = -1;
          int[] timestampsPart = new int[]{0,0,0,0,0,0,0};
          int partIdx = 0;
          for (int begin = pos; begin < pos + length; begin++) {
            byte b = buf[begin];
            if (b == '-' || b == ' ' || b == ':') {
              partIdx++;
              continue;
            }
            if (b == '.') {
              partIdx++;
              nanoBegin = begin;
              continue;
            }
            if (b < '0' || b > '9') {
              throw new SQLException(
                  "cannot parse data in timestamp string '" + new String(buf, pos, length, StandardCharsets.UTF_8) + "'");
            }
  
            timestampsPart[partIdx] = timestampsPart[partIdx] * 10 + b - 48;
          }
          if (timestampsPart[0] == 0
              && timestampsPart[1] == 0
              && timestampsPart[2] == 0
              && timestampsPart[3] == 0
              && timestampsPart[4] == 0
              && timestampsPart[5] == 0
              && timestampsPart[6] == 0) {
            lastValueNull |= BIT_LAST_ZERO_DATE;
            return null;
          }
  
          //fix non leading tray for nanoseconds
          if (nanoBegin > 0) {
            for (int begin = 0; begin < 6 - (pos + length - nanoBegin - 1); begin++) {
              timestampsPart[6] = timestampsPart[6] * 10;
            }
          }
  
          Timestamp timestamp;
  
          Calendar calendar;
          if (userCalendar != null) {
            calendar = userCalendar;
          } else if (columnInfo.getColumnType().getSqlType() == Types.TIMESTAMP) {
            calendar = Calendar.getInstance(timeZone);
          } else {
            calendar = Calendar.getInstance();
          }
  
          synchronized (calendar) {
            calendar.clear();
            calendar.set(Calendar.YEAR, timestampsPart[0]);
            calendar.set(Calendar.MONTH, timestampsPart[1] - 1);
            calendar.set(Calendar.DAY_OF_MONTH, timestampsPart[2]);
            calendar.set(Calendar.HOUR_OF_DAY, timestampsPart[3]);
            calendar.set(Calendar.MINUTE, timestampsPart[4]);
            calendar.set(Calendar.SECOND, timestampsPart[5]);
            calendar.set(Calendar.MILLISECOND, timestampsPart[6] / 1000000);
            timestamp = new Timestamp(calendar.getTime().getTime());
          }
          timestamp.setNanos(timestampsPart[6] * 1000);
          return timestamp;
  
        case TIME:
          //time does not go after millisecond
          String rawValue = new String(buf, pos, length, StandardCharsets.UTF_8);
          Timestamp tt = new Timestamp(getInternalTime(columnInfo, userCalendar, timeZone).getTime());
          tt.setNanos(extractNanos(rawValue));
          return tt;
  
  
        default:
          String value = new String(buf, pos, length, StandardCharsets.UTF_8);
          throw new SQLException("Value type \"" + columnInfo.getColumnType().getTypeName()
              + "\" with value \"" + value + "\" cannot be parse as Timestamp");
      }
    }