@Test
 public void monthsBetween() {
   assertThat(
       MONTHS.between(
           PlainTimestamp.of(2012, 1, 31, 12, 45), PlainTimestamp.of(2012, 2, 29, 12, 45)),
       is(0L));
   assertThat(
       MONTHS.between(
           PlainTimestamp.of(2012, 1, 31, 12, 45), PlainTimestamp.of(2012, 2, 29, 12, 44, 59)),
       is(0L));
   assertThat(
       MONTHS.between(
           PlainTimestamp.of(2012, 1, 29, 12, 45), PlainTimestamp.of(2012, 2, 29, 12, 45)),
       is(1L));
   assertThat(
       MONTHS.between(
           PlainTimestamp.of(2012, 1, 29, 12, 45), PlainTimestamp.of(2012, 2, 29, 12, 44, 59)),
       is(0L));
   assertThat(
       PlainTimestamp.of(2012, 1, 29, 12, 45)
           .until(PlainTimestamp.of(2012, 3, 28, 12, 44, 59), MONTHS.withCarryOver()),
       is(1L));
 }
  @Override
  public SwaptionSecurity createSecurity() {
    final int optionLength = getRandom(OPTION_LENGTH);
    ZonedDateTime expiry = ZonedDateTime.now().plusMonths(optionLength);
    final SwapSecurity underlying = createUnderlying(expiry.plusMonths(2), expiry);
    final Currency currency = FinancialSecurityUtils.getCurrency(underlying);
    expiry = nextWorkingDay(expiry, currency);
    final boolean isPayer = getRandom().nextBoolean();
    final boolean isLong = getRandom().nextBoolean();
    final boolean isCashSettled = getRandom().nextBoolean();
    final ZonedDateTime settlementDate = nextWorkingDay(expiry.plusDays(2), currency);
    final Double notional =
        underlying
            .getPayLeg()
            .getNotional()
            .accept(
                new NotionalVisitor<Double>() {

                  @Override
                  public Double visitCommodityNotional(final CommodityNotional notional) {
                    return null;
                  }

                  @Override
                  public Double visitInterestRateNotional(final InterestRateNotional notional) {
                    return notional.getAmount();
                  }

                  @Override
                  public Double visitSecurityNotional(final SecurityNotional notional) {
                    return null;
                  }

                  @Override
                  public Double visitVarianceSwapNotional(final VarianceSwapNotional notional) {
                    return notional.getAmount();
                  }
                });
    if (notional == null) {
      return null;
    }
    Double rate = getRate(underlying.getPayLeg());
    if (rate == null) {
      rate = getRate(underlying.getReceiveLeg());
      if (rate == null) {
        return null;
      }
    }
    final SwaptionSecurity security =
        new SwaptionSecurity(
            isPayer,
            getSecurityPersister().storeSecurity(underlying).iterator().next(),
            isLong,
            new Expiry(expiry),
            isCashSettled,
            currency,
            notional,
            new EuropeanExerciseType(),
            settlementDate);
    security.setName(
        createName(
            currency,
            optionLength,
            (int) MONTHS.between(underlying.getEffectiveDate(), underlying.getMaturityDate()),
            notional,
            rate));
    return security;
  }