class RatesCalibrationCsvLoader {

  @VisibleForTesting
  static IborFutureCurveNode curveIborFutureCurveNode(
      String conventionStr,
      String timeStr,
      String label,
      QuoteId quoteId,
      double spread,
      CurveNodeDate date,
      CurveNodeDateOrder order) {

    Matcher matcher = FUT_TIME_REGEX.matcher(timeStr.toUpperCase(Locale.ENGLISH));
    Matcher matcher2 = FUT_MONTH_REGEX.matcher(timeStr.toUpperCase(Locale.ENGLISH));
    SequenceDate seqDate = null;
    if (matcher.matches()) {
      Period periodToStart = Period.parse("P" + matcher.group(1));
      int sequenceNumber = Integer.parseInt(matcher.group(2));
      String seqType = matcher.group(3);
      if ("F".equals(seqType)) {
        seqDate = SequenceDate.full(periodToStart, sequenceNumber);
      } else {
        seqDate = SequenceDate.base(periodToStart, sequenceNumber);
      }
    } else if (matcher2.matches()) {
      YearMonth yearMonth = YearMonth.parse(matcher2.group(1), YM_FORMATTER);
      seqDate = SequenceDate.base(yearMonth);
    } else {
      throw new IllegalArgumentException(Messages.format("Invalid time format for Ibor Future: {}", timeStr));
    }
    IborFutureContractSpec contractSpec = IborFutureContractSpec.of(conventionStr);
    IborFutureTemplate template = IborFutureTemplate.of(seqDate, contractSpec);
    return IborFutureCurveNode.builder()
        .template(template)
        .rateId(quoteId)
        .additionalSpread(spread)
        .label(label)
        .date(date)
        .dateOrder(order)
        .build();
  }

  private  RatesCalibrationCsvLoader();

}