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 java.util.Collections;
36  
37  import org.joda.time.LocalDate;
38  
39  import net.objectlab.kit.datecalc.common.AbstractDateCalculator;
40  import net.objectlab.kit.datecalc.common.DateCalculator;
41  import net.objectlab.kit.datecalc.common.DefaultHolidayCalendar;
42  import net.objectlab.kit.datecalc.common.HolidayCalendar;
43  import net.objectlab.kit.datecalc.common.HolidayHandler;
44  import net.objectlab.kit.datecalc.common.WorkingWeek;
45  
46  /**
47   * This class is used via the DateCalculator interface, it enables the handling
48   * of different HolidayHandler, if no HolidayHandler is defined, the calendar
49   * will NOT move a date, even if it falls on a holiday or weekend.
50   *
51   * @author Benoit Xhenseval
52   *
53   */
54  public class LocalDateCalculator extends AbstractDateCalculator<LocalDate> {
55  
56      private JodaWorkingWeek workingWeek = JodaWorkingWeek.DEFAULT;
57  
58      public LocalDateCalculator() {
59          this(null, null, new DefaultHolidayCalendar<LocalDate>(Collections.<LocalDate> emptySet()), null);
60      }
61  
62      public LocalDateCalculator(final String name, final LocalDate startDate, final HolidayCalendar<LocalDate> holidayCalendar,
63              final HolidayHandler<LocalDate> holidayHandler) {
64          super(name, holidayCalendar, holidayHandler);
65          if (startDate != null) {
66              setStartDate(startDate);
67          }
68      }
69  
70      /**
71       * Set the working week.
72       * @param week the JodaWorkingWeek
73       * @throws IllegalArgumentException if the week is not a JodaWorkingWeek.
74       */
75      @Override
76      public DateCalculator<LocalDate> setWorkingWeek(final WorkingWeek week) {
77          if (week instanceof JodaWorkingWeek) {
78              workingWeek = (JodaWorkingWeek) week;
79              return this;
80          }
81          throw new IllegalArgumentException("Please give an instance of JodaWorkingWeek");
82      }
83  
84      /**
85       * is the date a non-working day according to the WorkingWeek?
86       */
87      @Override
88      public boolean isWeekend(final LocalDate date) {
89          assert workingWeek != null;
90          return !workingWeek.isWorkingDay(date);
91      }
92  
93      // -----------------------------------------------------------------------
94      //
95      // ObjectLab, world leaders in the design and development of bespoke
96      // applications for the securities financing markets.
97      // www.ObjectLab.co.uk
98      //
99      // -----------------------------------------------------------------------
100 
101     @Override
102     public DateCalculator<LocalDate> moveByDays(final int days) {
103         setCurrentIncrement(days);
104 
105         setCurrentBusinessDate(getCurrentBusinessDate().plusDays(days));
106 
107         if (getHolidayHandler() != null) {
108             setCurrentBusinessDate(getHolidayHandler().moveCurrentDate(this));
109         }
110 
111         return this;
112     }
113 
114     @Override
115     public DateCalculator<LocalDate> moveByMonths(final int months) {
116         setCurrentIncrement(months);
117 
118         setCurrentBusinessDate(getCurrentBusinessDate().plusMonths(months));
119 
120         if (getHolidayHandler() != null) {
121             setCurrentBusinessDate(getHolidayHandler().moveCurrentDate(this));
122         }
123 
124         return this;
125     }
126 
127     @Override
128     protected DateCalculator<LocalDate> createNewCalculator(final String name, final LocalDate startDate, final HolidayCalendar<LocalDate> holidays,
129             final HolidayHandler<LocalDate> handler) {
130         return new LocalDateCalculator(name, startDate, holidays, handler);
131     }
132 
133     @Override
134     protected LocalDate getToday() {
135         return new LocalDate();
136     }
137 
138     @Override
139     protected LocalDate compareDate(final LocalDate date1, final LocalDate date2, final boolean returnEarliest) {
140         if (date1 == null || date2 == null) {
141             return null;
142         }
143         if (returnEarliest) {
144             return date1.isAfter(date2) ? date2 : date1;
145         } else {
146             return date2.isAfter(date1) ? date2 : date1;
147         }
148     }
149 
150     @Override
151     protected void checkBoundary(final LocalDate date) {
152         final LocalDate early = getHolidayCalendar().getEarlyBoundary();
153         if (early != null && early.isAfter(date)) {
154             throw new IndexOutOfBoundsException(date + " is before the early boundary " + early);
155         }
156 
157         final LocalDate late = getHolidayCalendar().getLateBoundary();
158         if (late != null && late.isBefore(date)) {
159             throw new IndexOutOfBoundsException(date + " is after the late boundary " + late);
160         }
161     }
162 
163     @Override
164     protected LocalDate clone(final LocalDate date) {
165         return date;
166     }
167 
168     @Override
169     public int getNumberOfBusinessDaysBetween(final LocalDate d1, final LocalDate d2) {
170         if (d1 == null || d2 == null) {
171             return 0;
172         }
173         final boolean d1B4d2 = !d1.isAfter(d2);
174         LocalDate start = d1B4d2 ? d1 : d2;
175         LocalDate end = d1B4d2 ? d2 : d1;
176         if (getHolidayHandler() != null) {
177             start = getHolidayHandler().adjustDate(start, 1, this);
178         }
179 
180         int count = 0;
181         // start = start.plusDays(1);
182         while (start.isBefore(end)) {
183             if (!isNonWorkingDay(start)) {
184                 count++;
185             }
186             start = start.plusDays(1);
187         }
188         return d1B4d2 ? count : -count;
189     }
190 }
191 
192 /*
193  * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
194  *
195  * Based in London, we are world leaders in the design and development
196  * of bespoke applications for the securities financing markets.
197  *
198  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
199  *           ___  _     _           _   _          _
200  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
201  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
202  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
203  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
204  *                   |__/
205  *
206  *                     www.ObjectLab.co.uk
207  */