001/* 002 * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit. 003 * 004 * Based in London, we are world leaders in the design and development 005 * of bespoke applications for the securities financing markets. 006 * 007 * <a href="http://www.objectlab.co.uk/open">Click here to learn more</a> 008 * ___ _ _ _ _ _ 009 * / _ \| |__ (_) ___ ___| |_| | __ _| |__ 010 * | | | | '_ \| |/ _ \/ __| __| | / _` | '_ \ 011 * | |_| | |_) | | __/ (__| |_| |__| (_| | |_) | 012 * \___/|_.__// |\___|\___|\__|_____\__,_|_.__/ 013 * |__/ 014 * 015 * www.ObjectLab.co.uk 016 * 017 * $Id$ 018 * 019 * Copyright 2006 the original author or authors. 020 * 021 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 022 * use this file except in compliance with the License. You may obtain a copy of 023 * the License at 024 * 025 * http://www.apache.org/licenses/LICENSE-2.0 026 * 027 * Unless required by applicable law or agreed to in writing, software 028 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 029 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 030 * License for the specific language governing permissions and limitations under 031 * the License. 032 */ 033package net.objectlab.kit.datecalc.jdk8; 034 035import static net.objectlab.kit.datecalc.common.IMMPeriod.QUARTERLY; 036 037import java.time.DayOfWeek; 038import java.time.LocalDate; 039import java.time.Month; 040import java.time.temporal.TemporalAdjusters; 041import java.util.ArrayList; 042import java.util.List; 043 044import net.objectlab.kit.datecalc.common.AbstractIMMDateCalculator; 045import net.objectlab.kit.datecalc.common.IMMPeriod; 046 047/** 048 * Joda <code>LocalDate</code> based implementation of the 049 * {@link net.objectlab.kit.datecalc.common.IMMDateCalculator}. 050 * 051 * @author Benoit Xhenseval 052 * 053 */ 054public class LocalDateIMMDateCalculator extends AbstractIMMDateCalculator<LocalDate> { 055 /** 056 * Returns a list of IMM dates between 2 dates, it will exclude the start 057 * date if it is an IMM date but would include the end date if it is an IMM. 058 * 059 * @param start 060 * start of the interval, excluded 061 * @param end 062 * end of the interval, may be included. 063 * @param period 064 * specify when the "next" IMM is, if quarterly then it is the 065 * conventional algorithm. 066 * @return list of IMM dates 067 */ 068 @Override 069 public List<LocalDate> getIMMDates(final LocalDate start, final LocalDate end, final IMMPeriod period) { 070 final List<LocalDate> dates = new ArrayList<>(); 071 072 LocalDate date = start; 073 while (true) { 074 date = getNextIMMDate(true, date, period); 075 if (!date.isAfter(end)) { 076 dates.add(date); 077 } else { 078 break; 079 } 080 } 081 082 return dates; 083 } 084 085 @Override 086 protected LocalDate getNextIMMDate(final boolean requestNextIMM, final LocalDate start, final IMMPeriod period) { 087 LocalDate date = start; 088 089 date = calculateIMMMonth(requestNextIMM, date, date.getMonth()); 090 091 LocalDate imm = calculate3rdWednesday(date); 092 final Month immMonth = imm.getMonth(); 093 final boolean isMarchSept = immMonth == Month.MARCH || immMonth == Month.SEPTEMBER; 094 095 switch (period) { 096 097 case BI_ANNUALY_JUN_DEC: 098 if (isMarchSept) { 099 imm = getNextIMMDate(requestNextIMM, imm, period); 100 } 101 break; 102 103 case BI_ANNUALY_MAR_SEP: 104 if (!isMarchSept) { 105 imm = getNextIMMDate(requestNextIMM, imm, period); 106 } 107 break; 108 109 case ANNUALLY: 110 // second jump 111 imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY); 112 // third jump 113 imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY); 114 // fourth jump 115 imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY); 116 // fifth jump 117 imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY); 118 break; 119 120 case QUARTERLY: 121 default: 122 break; 123 } 124 125 return imm; 126 } 127 128 // ----------------------------------------------------------------------- 129 // 130 // ObjectLab, world leaders in the design and development of bespoke 131 // applications for the securities financing markets. 132 // www.ObjectLab.co.uk 133 // 134 // ----------------------------------------------------------------------- 135 136 private LocalDate calculateIMMMonth(final boolean requestNextIMM, final LocalDate startDate, final Month month) { 137 int monthOffset; 138 LocalDate date = startDate; 139 switch (month) { 140 case MARCH: 141 case JUNE: 142 case SEPTEMBER: 143 case DECEMBER: 144 final LocalDate immDate = calculate3rdWednesday(date); 145 if (requestNextIMM && !date.isBefore(immDate)) { 146 date = date.plusMonths(MONTHS_IN_QUARTER); 147 } else if (!requestNextIMM && !date.isAfter(immDate)) { 148 date = date.minusMonths(MONTHS_IN_QUARTER); 149 } 150 break; 151 152 default: 153 if (requestNextIMM) { 154 monthOffset = (MONTH_IN_YEAR - month.getValue()) % MONTHS_IN_QUARTER; 155 date = date.plusMonths(monthOffset); 156 } else { 157 monthOffset = month.getValue() % MONTHS_IN_QUARTER; 158 date = date.minusMonths(monthOffset); 159 } 160 break; 161 } 162 return date; 163 } 164 165 /** 166 * Assumes that the month is correct, get the day for the 2rd wednesday. 167 * 168 * @param original 169 * the start date 170 * @return the 3rd Wednesday of the month 171 */ 172 private static LocalDate calculate3rdWednesday(final LocalDate original) { 173 return original.with(TemporalAdjusters.firstInMonth(DayOfWeek.WEDNESDAY)).plusWeeks(2); 174 } 175 176 /** 177 * Checks if a given date is an official IMM Date (3rd Wednesdays of 178 * March/June/Sept/Dec. 179 * 180 * @param date 181 * @return true if that date is an IMM date. 182 */ 183 @Override 184 public boolean isIMMDate(final LocalDate date) { 185 boolean same = false; 186 187 final List<LocalDate> dates = getIMMDates(date.minusDays(1), date, QUARTERLY); 188 189 if (!dates.isEmpty()) { 190 same = date.equals(dates.get(0)); 191 } 192 193 return same; 194 } 195} 196 197/* 198 * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit. 199 * 200 * Based in London, we are world leaders in the design and development 201 * of bespoke applications for the securities financing markets. 202 * 203 * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a> 204 * ___ _ _ _ _ _ 205 * / _ \| |__ (_) ___ ___| |_| | __ _| |__ 206 * | | | | '_ \| |/ _ \/ __| __| | / _` | '_ \ 207 * | |_| | |_) | | __/ (__| |_| |__| (_| | |_) | 208 * \___/|_.__// |\___|\___|\__|_____\__,_|_.__/ 209 * |__/ 210 * 211 * www.ObjectLab.co.uk 212 */