Coverage Report - net.objectlab.kit.datecalc.joda.LocalDateIMMDateCalculator
 
Classes in this File Line Coverage Branch Coverage Complexity
LocalDateIMMDateCalculator
100%
48/48
76%
30/39
4.8
LocalDateIMMDateCalculator$1
100%
1/1
N/A
4.8
 
 1  
 /*
 2  
  * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
 3  
  * 
 4  
  * Based in London, we are world leaders in the design and development 
 5  
  * of bespoke applications for the securities financing markets.
 6  
  * 
 7  
  * <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
 8  
  *           ___  _     _           _   _          _
 9  
  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
 10  
  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
 11  
  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
 12  
  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
 13  
  *                   |__/
 14  
  *
 15  
  *                     www.ObjectLab.co.uk
 16  
  *
 17  
  * $Id: LocalDateIMMDateCalculator.java 298 2010-03-13 00:49:41Z benoitx $
 18  
  * 
 19  
  * Copyright 2006 the original author or authors.
 20  
  *
 21  
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 22  
  * use this file except in compliance with the License. You may obtain a copy of
 23  
  * the License at
 24  
  *
 25  
  * http://www.apache.org/licenses/LICENSE-2.0
 26  
  *
 27  
  * Unless required by applicable law or agreed to in writing, software
 28  
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 29  
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 30  
  * License for the specific language governing permissions and limitations under
 31  
  * the License.
 32  
  */
 33  
 package net.objectlab.kit.datecalc.joda;
 34  
 
 35  
 import static net.objectlab.kit.datecalc.common.IMMPeriod.QUARTERLY;
 36  
 import static org.joda.time.DateTimeConstants.DECEMBER;
 37  
 import static org.joda.time.DateTimeConstants.JUNE;
 38  
 import static org.joda.time.DateTimeConstants.MARCH;
 39  
 import static org.joda.time.DateTimeConstants.SEPTEMBER;
 40  
 
 41  
 import java.util.ArrayList;
 42  
 import java.util.List;
 43  
 
 44  
 import net.objectlab.kit.datecalc.common.AbstractIMMDateCalculator;
 45  
 import net.objectlab.kit.datecalc.common.IMMPeriod;
 46  
 
 47  
 import org.joda.time.LocalDate;
 48  
 
 49  
 /**
 50  
  * Joda <code>LocalDate</code> based implementation of the
 51  
  * {@link net.objectlab.kit.datecalc.common.IMMDateCalculator}.
 52  
  * 
 53  
  * @author Benoit Xhenseval
 54  
  * @author $LastChangedBy: benoitx $
 55  
  * @version $Revision: 298 $ $Date: 2010-03-12 19:49:41 -0500 (Fri, 12 Mar 2010) $
 56  
  * 
 57  
  */
 58  83
 public class LocalDateIMMDateCalculator extends AbstractIMMDateCalculator<LocalDate> {
 59  
     protected static final int MONTHS_IN_QUARTER = 3;
 60  
 
 61  
     protected static final int MONTH_IN_YEAR = 12;
 62  
 
 63  
     protected static final int DAYS_IN_WEEK = 7;
 64  
 
 65  
     /**
 66  
      * Returns a list of IMM dates between 2 dates, it will exclude the start
 67  
      * date if it is an IMM date but would include the end date if it is an IMM.
 68  
      * 
 69  
      * @param start
 70  
      *            start of the interval, excluded
 71  
      * @param end
 72  
      *            end of the interval, may be included.
 73  
      * @param period
 74  
      *            specify when the "next" IMM is, if quarterly then it is the
 75  
      *            conventional algorithm.
 76  
      * @return list of IMM dates
 77  
      */
 78  
     public List<LocalDate> getIMMDates(final LocalDate start, final LocalDate end, final IMMPeriod period) {
 79  34
         final List<LocalDate> dates = new ArrayList<LocalDate>();
 80  
 
 81  34
         LocalDate date = start;
 82  
         while (true) {
 83  54
             date = getNextIMMDate(true, date, period);
 84  54
             if (!date.isAfter(end)) {
 85  20
                 dates.add(date);
 86  
             } else {
 87  
                 break;
 88  
             }
 89  
         }
 90  
 
 91  34
         return dates;
 92  
     }
 93  
 
 94  
     @Override
 95  
     protected LocalDate getNextIMMDate(final boolean requestNextIMM, final LocalDate start, final IMMPeriod period) {
 96  212
         LocalDate date = start;
 97  
 
 98  212
         final int month = date.getMonthOfYear();
 99  212
         date = calculateIMMMonth(requestNextIMM, date, month);
 100  
 
 101  212
         LocalDate imm = calculate3rdWednesday(date);
 102  212
         final int immMonth = imm.getMonthOfYear();
 103  212
         final boolean isMarchSept = immMonth == MARCH || immMonth == SEPTEMBER;
 104  
 
 105  212
         switch (period) {
 106  
         
 107  
         case BI_ANNUALY_JUN_DEC:
 108  8
             if (isMarchSept) {
 109  2
                 imm = getNextIMMDate(requestNextIMM, imm, period);
 110  
             }
 111  
             break;
 112  
             
 113  
         case BI_ANNUALY_MAR_SEP:
 114  10
             if (!isMarchSept) {
 115  4
                 imm = getNextIMMDate(requestNextIMM, imm, period);
 116  
             }
 117  
             break;
 118  
             
 119  
         case ANNUALLY:
 120  
             // second jump
 121  6
             imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY);
 122  
             // third jump
 123  6
             imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY);
 124  
             // fourth jump
 125  6
             imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY);
 126  
             // fifth jump
 127  6
             imm = getNextIMMDate(requestNextIMM, imm, QUARTERLY);
 128  2
             break;
 129  
         }
 130  
 
 131  212
         return imm;
 132  
     }
 133  
 
 134  
     // -----------------------------------------------------------------------
 135  
     //
 136  
     //    ObjectLab, world leaders in the design and development of bespoke 
 137  
     //          applications for the securities financing markets.
 138  
     //                         www.ObjectLab.co.uk
 139  
     //
 140  
     // -----------------------------------------------------------------------
 141  
 
 142  
     private LocalDate calculateIMMMonth(final boolean requestNextIMM, final LocalDate startDate, final int month) {
 143  212
         int monthOffset = 0;
 144  212
         LocalDate date = startDate;
 145  212
         switch (month) {
 146  
         case MARCH:
 147  
         case JUNE:
 148  
         case SEPTEMBER:
 149  
         case DECEMBER:
 150  164
             final LocalDate immDate = calculate3rdWednesday(date);
 151  164
             if (requestNextIMM && !date.isBefore(immDate)) {
 152  98
                 date = date.plusMonths(MONTHS_IN_QUARTER);
 153  66
             } else if (!requestNextIMM && !date.isAfter(immDate)) {
 154  24
                 date = date.minusMonths(MONTHS_IN_QUARTER);
 155  
             }
 156  
             break;
 157  
 
 158  
         default:
 159  48
             if (requestNextIMM) {
 160  30
                 monthOffset = (MONTH_IN_YEAR - month) % MONTHS_IN_QUARTER;
 161  30
                 date = date.plusMonths(monthOffset);
 162  
             } else {
 163  18
                 monthOffset = month % MONTHS_IN_QUARTER;
 164  18
                 date = date.minusMonths(monthOffset);
 165  
             }
 166  
             break;
 167  
         }
 168  212
         return date;
 169  
     }
 170  
 
 171  
     /**
 172  
      * Assumes that the month is correct, get the day for the 2rd wednesday.
 173  
      * 
 174  
      * @param original
 175  
      *            the start date
 176  
      * @return the 3rd Wednesday of the month
 177  
      */
 178  
     private LocalDate calculate3rdWednesday(final LocalDate original) {
 179  376
         final LocalDate firstOfMonth = original.withDayOfMonth(1);
 180  376
         LocalDate firstWed = firstOfMonth.withDayOfWeek(MONTHS_IN_QUARTER);
 181  376
         if (firstWed.isBefore(firstOfMonth)) {
 182  288
             firstWed = firstWed.plusWeeks(1);
 183  
         }
 184  376
         return firstWed.plusWeeks(2);
 185  
     }
 186  
 
 187  
     /**
 188  
      * Checks if a given date is an official IMM Date (3rd Wednesdays of
 189  
      * March/June/Sept/Dec.
 190  
      * 
 191  
      * @param date
 192  
      * @return true if that date is an IMM date.
 193  
      */
 194  
     public boolean isIMMDate(final LocalDate date) {
 195  26
         boolean same = false;
 196  
 
 197  26
         final List<LocalDate> dates = getIMMDates(date.minusDays(1), date, QUARTERLY);
 198  
 
 199  26
         if (!dates.isEmpty()) {
 200  8
             same = date.equals(dates.get(0));
 201  
         }
 202  
 
 203  26
         return same;
 204  
     }
 205  
 }
 206  
 
 207  
 /*
 208  
  * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
 209  
  * 
 210  
  * Based in London, we are world leaders in the design and development 
 211  
  * of bespoke applications for the securities financing markets.
 212  
  * 
 213  
  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
 214  
  *           ___  _     _           _   _          _
 215  
  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
 216  
  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
 217  
  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
 218  
  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
 219  
  *                   |__/
 220  
  *
 221  
  *                     www.ObjectLab.co.uk
 222  
  */