/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.convention.expirycalc; import org.threeten.bp.LocalDate; import org.threeten.bp.temporal.TemporalAdjusters; import com.opengamma.financial.convention.calendar.Calendar; import com.opengamma.financial.convention.calendar.MondayToFridayCalendar; import com.opengamma.util.ArgumentChecker; /** * */ public class DaysFromEndOfMonthExpiryAdjuster implements ExchangeTradedInstrumentExpiryCalculator { /** A weekend calendar */ private static final Calendar WEEKEND = new MondayToFridayCalendar("Weekend"); /** The name of this adjuster */ private static final String NAME = "DaysFromEndOfMonthExpiryAdjuster"; /** The number of working days from last working day of the month */ private final int _nWorkingDays; /** * @param nWorkingDays The number of working days */ public DaysFromEndOfMonthExpiryAdjuster(final int nWorkingDays) { ArgumentChecker.notNegative(nWorkingDays, "nWorkingDays"); _nWorkingDays = nWorkingDays; } @Override public LocalDate getExpiryDate(final int n, final LocalDate today, final Calendar holidayCalendar) { ArgumentChecker.isTrue(n > 0, "n must be greater than 0; have {}", n); ArgumentChecker.notNull(today, "today"); ArgumentChecker.notNull(holidayCalendar, "holidayCalendar"); // is today after the adjusted date for this month LocalDate date = today.with(TemporalAdjusters.lastDayOfMonth()); while (!WEEKEND.isWorkingDay(date)) { date = date.minusDays(1); } int i = 0; while (i < _nWorkingDays) { date = date.minusDays(1); if (WEEKEND.isWorkingDay(date)) { i++; } } if (today.isAfter(date)) { return getExpiryDate(n, today.plusMonths(1).with(TemporalAdjusters.firstDayOfMonth()), WEEKEND); } date = today.plusMonths(n - 1).with(TemporalAdjusters.lastDayOfMonth()); while (!WEEKEND.isWorkingDay(date)) { date = date.minusDays(1); } i = 0; while (i < _nWorkingDays) { date = date.minusDays(1); if (WEEKEND.isWorkingDay(date)) { i++; } } return date; } @Override public LocalDate getExpiryMonth(final int n, final LocalDate today) { ArgumentChecker.isTrue(n > 0, "n must be greater than zero"); ArgumentChecker.notNull(today, "today"); return today.plusMonths(n - 1); } @Override public String getName() { return NAME; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + _nWorkingDays; return result; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!(obj instanceof DaysFromEndOfMonthExpiryAdjuster)) { return false; } final DaysFromEndOfMonthExpiryAdjuster other = (DaysFromEndOfMonthExpiryAdjuster) obj; if (_nWorkingDays != other._nWorkingDays) { return false; } return true; } }