private LocalDate getNextExpiryMonth(final Month[] validMonths, final LocalDate dtCurrent) {
   Month mthCurrent = dtCurrent.getMonth();
   int idx = Arrays.binarySearch(validMonths, mthCurrent);
   if (Math.abs(idx) >= (validMonths.length - 1)) {
     return LocalDate.of(dtCurrent.getYear() + 1, validMonths[0], dtCurrent.getDayOfMonth());
   } else if (idx >= 0) {
     return dtCurrent.with(validMonths[idx + 1]);
   } else {
     return dtCurrent.with(validMonths[-idx + 1]);
   }
 }
 @Override
 /**
  * Given a LocalDate representing the valuation date and an integer representing the n'th expiry
  * after that date, returns a date in the expiry month Used in
  * BloombergFutureUtils.getExpiryCodeForSoybeanFutures()
  */
 public LocalDate getExpiryMonth(final int n, final LocalDate today) {
   ArgumentChecker.isTrue(n > 0, "n must be greater than zero");
   ArgumentChecker.notNull(today, "today");
   LocalDate expiryDate = today;
   for (int m = n; m > 0; m--) {
     expiryDate = getNextExpiryMonth(expiryDate);
   }
   if (expiryDate.getDayOfMonth() > 15) {
     expiryDate = getNextExpiryMonth(expiryDate);
   }
   // set day to first possible - used in getExpiryDate()
   return LocalDate.of(expiryDate.getYear(), expiryDate.getMonth(), 14);
 }