View Javadoc
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$
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 org.joda.time.LocalDate;
36  import org.joda.time.Period;
37  import org.joda.time.PeriodType;
38  
39  import net.objectlab.kit.datecalc.common.CalculatorConstants;
40  import net.objectlab.kit.datecalc.common.PeriodCountBasis;
41  import net.objectlab.kit.datecalc.common.PeriodCountCalculator;
42  
43  /**
44   * Joda <code>LocalDatePeriod</code> based implementation of the
45   * {@link net.objectlab.kit.datecalc.common.PeriodCountCalculator}.
46   *
47   * @author Benoit Xhenseval
48   *
49   */
50  public class LocalDatePeriodCountCalculator implements PeriodCountCalculator<LocalDate> {
51  
52      public int dayDiff(final LocalDate start, final LocalDate end, final PeriodCountBasis basis) {
53          int diff;
54  
55          switch (basis) {
56          case CONV_30_360:
57              diff = diffConv30v360(start, end);
58              break;
59  
60          case CONV_360E_ISDA:
61              diff = diff360EIsda(start, end);
62              break;
63  
64          case CONV_360E_ISMA:
65              diff = diff360EIsma(start, end);
66              break;
67          default:
68              final Period p = new Period(start, end, PeriodType.days());
69              diff = p.getDays();
70          }
71  
72          return diff;
73      }
74  
75      private int diff360EIsma(final LocalDate start, final LocalDate end) {
76          int dayStart = start.getDayOfMonth();
77          int dayEnd = end.getDayOfMonth();
78          if (dayEnd == CalculatorConstants.MONTH_31_DAYS) {
79              dayEnd = CalculatorConstants.MONTH_30_DAYS;
80          }
81          if (dayStart == CalculatorConstants.MONTH_31_DAYS) {
82              dayStart = CalculatorConstants.MONTH_30_DAYS;
83          }
84          return (end.getYear() - start.getYear()) * CalculatorConstants.YEAR_360 + (end.getMonthOfYear() - start.getMonthOfYear()) * CalculatorConstants.MONTH_30_DAYS + dayEnd - dayStart;
85      }
86  
87      private int diff360EIsda(final LocalDate start, final LocalDate end) {
88          if (start.equals(end)) {
89              return 0;
90          }
91          int dayStart = start.getDayOfMonth();
92          int dayEnd = end.getDayOfMonth();
93  
94          if (start.dayOfMonth().getMaximumValue() == dayStart) {
95              dayStart = CalculatorConstants.MONTH_30_DAYS;
96          }
97          if (end.getMonthOfYear() != 2 && end.dayOfMonth().getMaximumValue() == dayEnd) {
98              dayEnd = CalculatorConstants.MONTH_30_DAYS;
99          }
100 
101         return (end.getYear() - start.getYear()) * CalculatorConstants.YEAR_360 + (end.getMonthOfYear() - start.getMonthOfYear()) * CalculatorConstants.MONTH_30_DAYS + dayEnd - dayStart;
102     }
103 
104     private int diffConv30v360(final LocalDate start, final LocalDate end) {
105         int dayStart = start.getDayOfMonth();
106         int dayEnd = end.getDayOfMonth();
107         if (dayEnd == CalculatorConstants.MONTH_31_DAYS && dayStart >= CalculatorConstants.MONTH_30_DAYS) {
108             dayEnd = CalculatorConstants.MONTH_30_DAYS;
109         }
110         if (dayStart == CalculatorConstants.MONTH_31_DAYS) {
111             dayStart = CalculatorConstants.MONTH_30_DAYS;
112         }
113         return (end.getYear() - start.getYear()) * CalculatorConstants.YEAR_360 + (end.getMonthOfYear() - start.getMonthOfYear()) * CalculatorConstants.MONTH_30_DAYS + dayEnd - dayStart;
114     }
115 
116     // -----------------------------------------------------------------------
117     //
118     // ObjectLab, world leaders in the design and development of bespoke
119     // applications for the securities financing markets.
120     // www.ObjectLab.co.uk
121     //
122     // -----------------------------------------------------------------------
123 
124     public double monthDiff(final LocalDate start, final LocalDate end, final PeriodCountBasis basis) {
125         return yearDiff(start, end, basis) * CalculatorConstants.MONTHS_IN_YEAR;
126     }
127 
128     public double yearDiff(final LocalDate start, final LocalDate end, final PeriodCountBasis basis) {
129         double diff = 0.0;
130 
131         switch (basis) {
132         case ACT_ACT:
133             final int startYear = start.getYear();
134             final int endYear = end.getYear();
135             if (startYear != endYear) {
136                 final LocalDate endOfStartYear = start.dayOfYear().withMaximumValue();
137                 final LocalDate startOfEndYear = end.withDayOfYear(1);
138 
139                 final int diff1 = new Period(start, endOfStartYear, PeriodType.days()).getDays();
140                 final int diff2 = new Period(startOfEndYear, end, PeriodType.days()).getDays();
141                 diff = (diff1 + 1.0) / start.dayOfYear().getMaximumValue() + (endYear - startYear - 1.0)
142                         + (double) diff2 / (double) end.dayOfYear().getMaximumValue();
143             }
144             break;
145 
146         case CONV_30_360:
147         case CONV_360E_ISDA:
148         case CONV_360E_ISMA:
149         case ACT_360:
150             diff = dayDiff(start, end, basis) / CalculatorConstants.YEAR_360_0;
151             break;
152 
153         case ACT_365:
154             diff = dayDiff(start, end, basis) / CalculatorConstants.YEAR_365_0;
155             break;
156 
157         default:
158             throw new UnsupportedOperationException("Sorry ACT_UST is not supported");
159         }
160 
161         return diff;
162     }
163 }
164 
165 /*
166  * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
167  *
168  * Based in London, we are world leaders in the design and development
169  * of bespoke applications for the securities financing markets.
170  *
171  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
172  *           ___  _     _           _   _          _
173  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
174  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
175  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
176  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
177  *                   |__/
178  *
179  *                     www.ObjectLab.co.uk
180  */