1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
45
46
47
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
119
120
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180