/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics.ircurve; import org.threeten.bp.DayOfWeek; import org.threeten.bp.LocalDate; import org.threeten.bp.temporal.Temporal; import org.threeten.bp.temporal.TemporalAdjuster; import org.threeten.bp.temporal.TemporalAdjusters; import com.opengamma.util.ArgumentChecker; /** * {@code DatAdjuster} that finds the next given day of month in the next IMM Future Expiry Month. (EnumSet.of(Month.MARCH, Month.JUNE, Month.SEPTEMBER, Month.DECEMBER)) <p> * e.g. For IR Future Options, this is typically the 3rd Wednesday. For USD and GBP Equity Index Options, this is the Saturday after the Third Friday. <p> */ public class NextExpiryAdjuster implements TemporalAdjuster { /** An adjuster finding the DayOfWeek in the given week in a month. May be before or after date. */ private final TemporalAdjuster _dayOfMonthAdjuster; /** An adjuster moving to the next quarter. */ private final NextQuarterAdjuster _nextQuarterAdjuster; /** Specify the day and week in the month. (eg 3rd Wednesday) Adjuster returns that day in next IMM Expiry Month * @param week Ordinal of week in month, beginning from 1. * @param day DayOfWeek */ public NextExpiryAdjuster(final int week, final DayOfWeek day) { _dayOfMonthAdjuster = TemporalAdjusters.dayOfWeekInMonth(week, day); _nextQuarterAdjuster = new NextQuarterAdjuster(); } /** Specify the day and week in the month, plus an offset in number of days. Adjuster returns that day in next IMM Expiry Month. <p> * e.g. (3,DayOfWeek.FRIDAY,1) is the Saturday after the 3rd Friday in the month. This is different from the 3rd Saturday. * @param week Ordinal of week in month, beginning from 1. * @param day DayOfWeek * @param offset Integer offset, positive or negative from the result of week,day. */ public NextExpiryAdjuster(final int week, final DayOfWeek day, final int offset) { _dayOfMonthAdjuster = new DayOfWeekInMonthPlusOffsetAdjuster(week, day, offset); _nextQuarterAdjuster = new NextQuarterAdjuster(); } /** * Specify the day and week in the month, plus an offset in number of days. Adjuster returns that day in next IMM Expiry Month. <p> * @param dayOfMonthAdjuster provide the day of month adjuster directly */ public NextExpiryAdjuster(final TemporalAdjuster dayOfMonthAdjuster) { ArgumentChecker.notNull(dayOfMonthAdjuster, "dayOfMonthAdjuster"); _dayOfMonthAdjuster = dayOfMonthAdjuster; _nextQuarterAdjuster = new NextQuarterAdjuster(); } /** * @return the dayOfMonthAdjuster */ public final TemporalAdjuster getDayOfMonthAdjuster() { return _dayOfMonthAdjuster; } /** * @return the nextQuarterAdjuster */ public TemporalAdjuster getNextQuarterAdjuster() { return _nextQuarterAdjuster; } @Override public Temporal adjustInto(final Temporal temporal) { final LocalDate date = LocalDate.from(temporal); LocalDate result = date.with(_dayOfMonthAdjuster); if (_nextQuarterAdjuster.getFutureQuarters().contains(date.getMonth()) && result.isAfter(date)) { // in a quarter // CSIGNORE // do nothing } else { result = date.with(_nextQuarterAdjuster).with(_dayOfMonthAdjuster); } return temporal.with(result); } }