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.common;
034
035import java.util.List;
036
037/**
038 * A DateCalculator is a lightweight container with an optional reference to a
039 * set of holidays, a WorkingWeek (Mon-Fri by default), a startDate and a
040 * current business date. The Calculator also uses a HolidayHandler to determine
041 * what to do when the calculated current Business Date falls on a weekend or
042 * holiday (non-working day). The CurrentDate date is changed every time that the
043 * moveByDays or moveByBusinessDays methods are called. 'E' will be
044 * parameterized to be a Date-like class, i.e. java.util.Date or
045 * java.util.Calendar (and LocalDate or YearMonthDay for Joda-time / JDK8).
046 *
047 * @author Benoit Xhenseval
048 *
049 * @param <E>
050 *            a representation of a date, typically JDK: Date, Calendar;
051 *            Joda:LocalDate, YearMonthDay
052 *
053 */
054public interface DateCalculator<E> extends BaseCalculator<E> {
055
056    /**
057     * This is typically the name of the associated set of holidays.
058     *
059     * @return calculator name (Typically the name associated with the holiday
060     *         set).
061     */
062    String getName();
063
064    /**
065     * Setting the start date also sets the current business date (and if this
066     * is a non-working day, the current business date will be moved to the next
067     * business day acording to the HolidayHandler algorithm given).
068     *
069     * @param startDate
070     *            the reference date for this calculator, the current business
071     *            date is also updated and may be moved if it falls on a non
072     *            working day (holiday/weekend).
073     */
074    DateCalculator<E> setStartDate(E startDate);
075
076    /**
077     * Gives the startDate of this calculator (immutable once set via
078     * setStartDate).
079     *
080     * @return startDate the reference date for this calculator.
081     */
082    E getStartDate();
083
084    /**
085     * Is the given date falling on a weekend, according to the WorkingWeek.
086     *
087     * @return true if the date falls on a weekend.
088     */
089    boolean isWeekend(E date);
090
091    /**
092     * Is the current business day a non-working day, this is useful if the
093     * calculator does not have any algorithm to change the date when it falls
094     * on a non-working day. This method can then be used to show a warning to
095     * the user.
096     *
097     * @return true if the current date is either a weekend or a holiday.
098     */
099    boolean isCurrentDateNonWorking();
100
101    /**
102     * This is typically used at the construction of a DateCalculator to give a
103     * reference to a Holiday Calendar, if not the case, the calculator will
104     * make an immutable copy of the HolidayCalendar.
105     *
106     * @param calendar
107     *            the holiday calendar (if null, no holidays taken into account)
108     * @since 1.1.0
109     */
110    DateCalculator<E> setHolidayCalendar(HolidayCalendar<E> calendar);
111
112    // -----------------------------------------------------------------------
113    //
114    // ObjectLab, world leaders in the design and development of bespoke
115    // applications for the securities financing markets.
116    // www.ObjectLab.co.uk
117    //
118    // -----------------------------------------------------------------------
119
120    /**
121     * Returns an immutable version of the HolidayCalendar.
122     * @return a copy of the holiday calendar
123     * @since 1.1.0
124     */
125    HolidayCalendar<E> getHolidayCalendar();
126
127    /**
128     * Allows user to define what their Working Week should be (default is
129     * Mon-Fri).
130     *
131     * @param week
132     *            an immutable definition of a week.
133     */
134    DateCalculator<E> setWorkingWeek(WorkingWeek week);
135
136    /**
137     * Gives a current business date, it may be moved according to the
138     * HolidayHandler algorithm if it falls on a non-working day.
139     *
140     * @param date
141     * @return new current business date if moved.
142     */
143    E setCurrentBusinessDate(E date);
144
145    /**
146     * Gives a current business date, it will NOT be moved. Do NOT use this in 99.9% cases.
147     *
148     * @param date
149     * @return new current business date if moved.
150     */
151    E forceCurrentDateNoAdjustment(E date);
152
153    /**
154     * Gives the name of the holiday handler algorithm, see HolidayHandlerType
155     * for some standard values.
156     *
157     * @return the holiday handler type, can be null
158     */
159    String getHolidayHandlerType();
160
161    /**
162     * This changes the current business date held in the calculator, it moves
163     * the new current business date by the number of days and, if it falls on a
164     * weekend or holiday, moves it further according to the HolidayHandler
165     * given in this DateCalculator.
166     *
167     * @param days
168     *            number of days (can be &lt;0 or &gt;0)
169     * @return the DateCalculator (so one can do
170     *         calendar.moveByDays(-2).getCurrentBusinessDate();)
171     */
172    DateCalculator<E> moveByDays(int days);
173
174    /**
175     * This changes the current business date held in the calculator, it moves
176     * the current date by a number of business days, this means that if a date
177     * is either a 'weekend' or holiday along the way, it will be skipped
178     * acording to the holiday handler and not count towards the number of days
179     * to move.
180     *
181     * @param businessDays
182     *            (can be &lt;0 or &gt;0)
183     * @return the current DateCalculator (so one can do
184     *         calendar.moveByBusinessDays(2).getCurrentBusinessDate();)
185     * @exception IllegalArgumentException
186     *                if the HolidayHandlerType is (MODIFIED_PRECEDING or
187     *                BACKWARD) and businessDays &gt; 0 or (MODIFIED_FOLLOWING or
188     *                FORWARD) and businessDays &lt; 0
189     */
190    DateCalculator<E> moveByBusinessDays(int businessDays);
191
192    /**
193     * Allows DateCalculators to be combined into a new one, the startDate and
194     * currentBusinessDate will be the ones from the existing calendar (not the
195     * parameter one). The name will be combined name1+"/"+calendar.getName().
196     * If the Calendars have Early or Late boundaries, the result is the
197     * narrowest interval (e.g. the later Early boundary and the earliest
198     * Late boundary).
199     *
200     * @param calculator
201     *            return the same DateCalculator if calendar is null or the
202     *            original calendar (but why would you want to do that?)
203     * @throws IllegalArgumentException
204     *             if both calendars have different types of HolidayHandlers or
205     *             WorkingWeek; Also, it is required that BOTH calendars either
206     *             have Early/Late Boundaries or none.
207     */
208    DateCalculator<E> combine(DateCalculator<E> calculator);
209
210    /**
211     * Move the current date by a given tenor, please note that all tenors are
212     * relative to the SPOT day which is a number of days from the current date.
213     * This method therefore, calculates the SPOT day first, moves it if it
214     * falls on a holiday and then goes to the calculated day according to the
215     * Tenor.
216     *
217     * @param tenor
218     *            the Tenor to reach.
219     * @param spotLag
220     *            number of days to "spot" days, this can vary from one market
221     *            to the other. It is sometimes called "settlement interval"
222     *            or "offset".
223     * @return the current DateCalculator
224     */
225    DateCalculator<E> moveByTenor(Tenor tenor, int spotLag);
226
227    /**
228     * Move the current date by a given tenor, please note that all tenors are
229     * relative to the CURRENT day (and NOT from spot).
230     *
231     * @param tenor
232     *            the Tenor to reach.
233     * @return the current DateCalculator
234     * @since 1.1.0
235     */
236    DateCalculator<E> moveByTenor(Tenor tenor);
237
238    /**
239     * Calculate a series of Tenor codes in one go based on current day,
240     * this does NOT change the current business date.
241     *
242     * @return list of dates in same order as tenors.
243     * @since 1.1.0
244     */
245    List<E> calculateTenorDates(List<Tenor> tenors);
246
247    /**
248     * Calculate a series of Tenor codes in one go based on SPOT day (calculated
249     * with the spot lag), this does NOT change the current business date.
250     *
251     * @return list of dates in same order as tenors.
252     * @since 1.1.0
253     */
254    List<E> calculateTenorDates(List<Tenor> tenors, int spotLag);
255
256    /**
257     * This would be used by delegate methods to detect if the increment
258     * if positive or negative (this will allow us to define a Handler
259     * that can act as Forward if positive and Backward if negative).
260     * @param increment
261     */
262    DateCalculator<E> setCurrentIncrement(int increment);
263}
264
265/*
266 * ObjectLab, http://www.objectlab.co.uk/open is sponsoring the ObjectLab Kit.
267 *
268 * Based in London, we are world leaders in the design and development
269 * of bespoke applications for the securities financing markets.
270 *
271 * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
272 *           ___  _     _           _   _          _
273 *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
274 *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
275 *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
276 *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
277 *                   |__/
278 *
279 *                     www.ObjectLab.co.uk
280 */