BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlt_calendarutil.h
Go to the documentation of this file.
1/// @file bdlt_calendarutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlt_calendarutil.h -*-C++-*-
8#ifndef INCLUDED_BDLT_CALENDARUTIL
9#define INCLUDED_BDLT_CALENDARUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlt_calendarutil bdlt_calendarutil
15/// @brief Provide common date manipulations requiring a calendar.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlt
19/// @{
20/// @addtogroup bdlt_calendarutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlt_calendarutil-purpose"> Purpose</a>
25/// * <a href="#bdlt_calendarutil-classes"> Classes </a>
26/// * <a href="#bdlt_calendarutil-description"> Description </a>
27/// * <a href="#bdlt_calendarutil-usage"> Usage </a>
28/// * <a href="#bdlt_calendarutil-example-1-manipulating-dates-with-calendarutil"> Example 1: Manipulating Dates with CalendarUtil </a>
29///
30/// # Purpose {#bdlt_calendarutil-purpose}
31/// Provide common date manipulations requiring a calendar.
32///
33/// # Classes {#bdlt_calendarutil-classes}
34///
35/// - bdlt::CalendarUtil: common date manipulations requiring a calendar
36///
37/// @see bdlt_date, bdlt_calendar
38///
39/// # Description {#bdlt_calendarutil-description}
40/// This component provides a `struct`, `bdlt::CalendarUtil`, that
41/// serves as a namespace for date-manipulation functions that require the use
42/// of a calendar.
43///
44/// This utility component provides the following (static) methods:
45/// @code
46/// 'addBusinessDaysIfValid' Add an integral number of business days to the
47/// specified original date within the valid range
48/// of the specified calendar.
49///
50/// 'nthBusinessDayOfMonthOrMaxIfValid'
51/// Determine the 'n'th business day of the
52/// specified year and month subject to a maximum of
53/// the total number of business days in the
54/// specified year and month, based on the provided
55/// calendar.
56///
57/// 'shiftFollowingIfValid' If original date is not a business day, move
58/// the date forward until it is a business day.
59///
60/// 'shiftPrecedingIfValid' If original date is not a business day, move
61/// the date backwards until it is a business day.
62///
63/// 'shiftModifiedFollowingIfValid'
64/// If original date is not a business day, move
65/// the date forward until it is a business day,
66/// unless the date goes into the next month, in
67/// which case the date is moved to the previous
68/// business day.
69///
70/// 'shiftModifiedPrecedingIfValid'
71/// If original date is not a business day, move
72/// the date backward until it is a business day,
73/// unless the date goes into the previous month, in
74/// which case the date is moved to the next
75/// business day.
76///
77/// 'shiftIfValid' Shift a date based on a provided convention.
78/// Note that this function delegates its operation
79/// to one of the above shift functions, based on
80/// the date-shifting convention specified.
81///
82/// 'subtractBusinessDaysIfValid'
83/// Subtract an integral number of business days
84/// from the specified original date within the
85/// valid range of the specified calendar.
86/// @endcode
87///
88/// ## Usage {#bdlt_calendarutil-usage}
89///
90///
91/// This section illustrates intended use of this component.
92///
93/// ### Example 1: Manipulating Dates with CalendarUtil {#bdlt_calendarutil-example-1-manipulating-dates-with-calendarutil}
94///
95///
96/// Suppose that we want to determine the actual interest payment date in
97/// January 2014 from a US bond that pays on the 20th of each month and uses the
98/// modified-following date-shifting convention.
99///
100/// We create a calendar, `calUS`, that has the calendar information populated
101/// for the US in 2014. We then use the `shiftIfValid` function, provided by
102/// `CalendarUtil`, to compute the payment date.
103///
104/// First, we create a date for January 1, 2014 that corresponds to the nominal
105/// payment date (which happens to be holiday) and a calendar with valid range
106/// from April 20, 2012 through April 20, 2014, typical weekend days, and the
107/// holiday:
108/// @code
109/// const bdlt::Date unadjustedDate(2014, 1, 20);
110///
111/// const bdlt::Date startDate(2012, 4, 20);
112/// const bdlt::Date endDate(2014, 4, 20);
113///
114/// bdlt::Calendar calUS(startDate, endDate);
115/// calUS.addWeekendDay(bdlt::DayOfWeek::e_SAT);
116/// calUS.addWeekendDay(bdlt::DayOfWeek::e_SUN);
117/// calUS.addHoliday(unadjustedDate);
118/// @endcode
119/// Now, we determine the actual payment date by invoking the `shiftIfValid`
120/// function:
121/// @code
122/// bdlt::Date result;
123/// int status = CalendarUtil::shiftIfValid(
124/// &result,
125/// unadjustedDate,
126/// calUS,
127/// CalendarUtil::e_MODIFIED_FOLLOWING);
128/// @endcode
129/// Notice that `e_MODIFIED_FOLLOWING` is specified as an argument to
130/// `shiftIfValid` to indicate that we want to use the modified-following
131/// date-shifting convention.
132///
133/// Finally, we verify that the resulting date is correct:
134/// @code
135/// const bdlt::Date expected(2014, 1, 21);
136///
137/// assert(0 == status);
138/// assert(expected == result);
139/// @endcode
140/// @}
141/** @} */
142/** @} */
143
144/** @addtogroup bdl
145 * @{
146 */
147/** @addtogroup bdlt
148 * @{
149 */
150/** @addtogroup bdlt_calendarutil
151 * @{
152 */
153
154#include <bdlscm_version.h>
155
156#include <bdlt_calendar.h>
158#include <bdlt_date.h>
159#include <bdlt_dayofweek.h>
160
161#include <bsls_assert.h>
162#include <bsls_review.h>
163
164
165namespace bdlt {
166
167 // ===================
168 // struct CalendarUtil
169 // ===================
170
171/// This `struct` provides a namespace for utility functions that operate on
172/// dates in the context of supplied calendars.
174
175 // TYPES
176
177 /// Enumeration used to delineate various date-shifting conventions.
179
180 e_UNADJUSTED, // The date is not adjusted.
181
182 e_FOLLOWING, // The date is adjusted using
183 // 'shiftFollowingIfValid'.
184
185 e_PRECEDING, // The date is adjusted using
186 // 'shiftPrecedingIfValid'.
187
188 e_MODIFIED_FOLLOWING, // The date is adjusted using
189 // 'shiftModifiedFollowingIfValid'.
190
191 e_MODIFIED_PRECEDING // The date is adjusted using
192 // 'shiftModifiedPrecedingIfValid'.
193 };
194
195 // CLASS METHODS
196
197 /// Load, into the specified `result`, the date that is the specified
198 /// `numBusinessDays` chronologically after the specified `original`
199 /// date according to the specified `calendar`. The resulting date is
200 /// chronologically before the `original` date for negative values of
201 /// `numBusinessDays`, the chronologically earliest business day that is
202 /// on or after the `original` date for `0 == numBusinessDays`, and
203 /// chronologically after the `original` date for positive values of
204 /// `numBusinessDays`. Return 0 on success, and a non-zero value,
205 /// without modifying `*result`, if either the `original` date or the
206 /// resulting date is not within the valid range of `calendar`. Note
207 /// that if `0 != numBusinessDays`, then the result of
208 /// `addBusinessDaysIfValid(res, orig, cal, numBusinessDays)` is
209 /// identical to the result of
210 /// `subtractBusinessDaysIfValid(res, orig, cal, -numBusinessDays)`.
212 const bdlt::Date& original,
213 const bdlt::Calendar& calendar,
214 int numBusinessDays);
215
216 /// Load, into the specified `result`, the date corresponding to the
217 /// specified `n`th business day of the specified `month` and the
218 /// specified `year` based on the specified `calendar`. A positive
219 /// value of `n` indicates that counting the number of business days
220 /// begins from the first calendar date of the month (inclusive), and a
221 /// negative value of `n` indicates that counting the number of business
222 /// days begins from the last calendar date of the month (inclusive).
223 /// If there are fewer than `abs(n)` business days in the month
224 /// according to the `calendar`, the business day furthest from the
225 /// first date of the month is chosen if `n > 0`, and the business day
226 /// furthest from the last date of the month is chosen if `n < 0`.
227 /// Return 0 on success, and a non-zero value, without modifying
228 /// `*result`, if the entire month specified by `year` and `month` is
229 /// not within the valid range of the `calendar` or there are no
230 /// business days in the month specified by `year` and `month`. The
231 /// behavior is undefined unless `n != 0`, `1 <= year <= 9999`, and
232 /// `1 <= month <= 12`.
234 bdlt::Date *result,
235 const bdlt::Calendar& calendar,
236 int year,
237 int month,
238 int n);
239
240 /// Load, into the specified `result`, the date of the chronologically
241 /// earliest business day that is on or after the specified `original`
242 /// date based on the specified `calendar`. Return 0 on success, and a
243 /// non-zero value, without modifying `*result`, if the `original` date
244 /// is not within the valid range of `calendar` or the following
245 /// business day cannot be found within the valid range of `calendar`.
246 static int shiftFollowingIfValid(bdlt::Date *result,
247 const bdlt::Date& original,
248 const bdlt::Calendar& calendar);
249
250 /// Load, into the specified `result`, the date of the business day that
251 /// is derived from the specified `original` date based on the specified
252 /// `calendar` according to the specified date-shifting `convention`.
253 /// Return 0 on success, and a non-zero value, without modifying
254 /// `*result`, if a valid business date cannot be found according to the
255 /// `convention` within the valid range of `calendar`.
256 static int shiftIfValid(bdlt::Date *result,
257 const bdlt::Date& original,
258 const bdlt::Calendar& calendar,
259 ShiftConvention convention);
260
261 /// Load, into the specified `result`, the date of the business day that
262 /// is derived from the specified `original` date based on the specified
263 /// `calendar` according to the specified date-shifting `convention`,
264 /// except when the `original` is either the specified `specialDay` of
265 /// the week, or - if the specified `extendSpecialDay` is `true` - one
266 /// of the (possibly empty) set of contiguous non-business days
267 /// immediately *preceding* a `specialDay` according to the `calendar`,
268 /// in which case the `result` is determined using the specified
269 /// `specialConvention`. Return 0 on success, and a non-zero value,
270 /// without modifying `*result`, if a valid business date cannot be
271 /// found according to the above algorithm within the valid range of
272 /// `calendar`. Note that this method is useful for computing, for
273 /// example, Korean bond coupon payment dates.
274 static int shiftIfValid(bdlt::Date *result,
275 const bdlt::Date& original,
276 const bdlt::Calendar& calendar,
277 ShiftConvention convention,
278 bdlt::DayOfWeek::Enum specialDay,
279 bool extendSpecialDay,
280 ShiftConvention specialConvention);
281
282 /// Load, into the specified `result`, the date of the chronologically
283 /// earliest business day that is on or after the specified `original`
284 /// date, unless a date cannot be found in the same month, in which case
285 /// load the chronologically latest business day before the `original`
286 /// date based on the specified `calendar`. Return 0 on success, and a
287 /// non-zero value, without modifying `*result`, if the `original` date
288 /// is not within the valid range of `calendar` or a valid business date
289 /// cannot be found according to the above algorithm within the valid
290 /// range of `calendar`.
292 const bdlt::Date& original,
293 const bdlt::Calendar& calendar);
294
295 /// Load, into the specified `result`, the date of the chronologically
296 /// latest business day that is on or before the specified `original`
297 /// date, unless a date cannot be found in the same month, in which case
298 /// load the chronologically earliest business day after the `original`
299 /// date based on the specified `calendar`. Return 0 on success, and a
300 /// non-zero value, without modifying `*result`, if the `original` date
301 /// is not within the valid range of `calendar` or a valid business date
302 /// cannot be found according to the above algorithm within the valid
303 /// range of `calendar`.
305 const bdlt::Date& original,
306 const bdlt::Calendar& calendar);
307
308 /// Load, into the specified `result`, the date of the chronologically
309 /// latest business day that is on or before the specified `original`
310 /// date based on the specified `calendar`. Return 0 on success, and a
311 /// non-zero value, without modifying `*result`, if the `original` date
312 /// is not within the valid range of `calendar` or the preceding
313 /// business day cannot be found within the valid range of `calendar`.
314 static int shiftPrecedingIfValid(bdlt::Date *result,
315 const bdlt::Date& original,
316 const bdlt::Calendar& calendar);
317
318 /// Load, into the specified `result`, the date that is the specified
319 /// `numBusinessDays` chronologically before the specified `original`
320 /// date according to the specified `calendar`. The resulting date is
321 /// chronologically before the `original` date for positive values of
322 /// `numBusinessDays`, the chronologically latest business day that is
323 /// on or before the `original` date for `0 == numBusinessDays`, and
324 /// chronologically after the `original` date for negative values of
325 /// `numBusinessDays`. Return 0 on success, and a non-zero value,
326 /// without modifying `*result`, if either the `original` date or the
327 /// resulting date is not within the valid range of `calendar`. Note
328 /// that if `0 != numBusinessDays`, then the result of
329 /// `subtractBusinessDaysIfValid(res, orig, cal, numBusinessDays)` is
330 /// identical to the result of
331 /// `addBusinessDaysIfValid(res, orig, cal, -numBusinessDays)`.
333 bdlt::Date *result,
334 const bdlt::Date& original,
335 const bdlt::Calendar& calendar,
336 int numBusinessDays);
337};
338
339// ============================================================================
340// INLINE DEFINITIONS
341// ============================================================================
342
343 // -------------------
344 // struct CalendarUtil
345 // -------------------
346
347// CLASS METHODS
348inline
350 const bdlt::Date& original,
351 const bdlt::Calendar& calendar)
352{
353 BSLS_ASSERT(result);
354
355 enum {
356 e_SUCCESS = 0,
357 e_BAD_INPUT = 1,
358 e_OUT_OF_RANGE = 2,
359 e_NOT_FOUND = 3
360 };
361
362 if (!calendar.isInRange(original)) {
363 return e_BAD_INPUT; // RETURN
364 }
365
367 calendar.beginBusinessDays(original);
368 if (iter != calendar.endBusinessDays()) {
369 *result = *iter;
370 return e_SUCCESS; // RETURN
371 }
372 else {
373 return e_OUT_OF_RANGE; // RETURN
374 }
375
376 return e_NOT_FOUND;
377}
378
379inline
381 const bdlt::Date& original,
382 const bdlt::Calendar& calendar)
383{
384 BSLS_ASSERT(result);
385
386 enum {
387 e_SUCCESS = 0,
388 e_BAD_INPUT = 1,
389 e_OUT_OF_RANGE = 2,
390 e_NOT_FOUND = 3
391 };
392
393 if (!calendar.isInRange(original)) {
394 return e_BAD_INPUT; // RETURN
395 }
396
398 calendar.rbeginBusinessDays(original);
399 if (iter != calendar.rendBusinessDays()) {
400 *result = *iter;
401 return e_SUCCESS; // RETURN
402 }
403 else {
404 return e_OUT_OF_RANGE; // RETURN
405 }
406
407 return e_NOT_FOUND;
408}
409
410} // close package namespace
411
412
413#endif
414
415// ----------------------------------------------------------------------------
416// Copyright 2018 Bloomberg Finance L.P.
417//
418// Licensed under the Apache License, Version 2.0 (the "License");
419// you may not use this file except in compliance with the License.
420// You may obtain a copy of the License at
421//
422// http://www.apache.org/licenses/LICENSE-2.0
423//
424// Unless required by applicable law or agreed to in writing, software
425// distributed under the License is distributed on an "AS IS" BASIS,
426// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
427// See the License for the specific language governing permissions and
428// limitations under the License.
429// ----------------------------- END-OF-FILE ----------------------------------
430
431/** @} */
432/** @} */
433/** @} */
Definition bdlt_calendarreverseiteratoradapter.h:298
Definition bdlt_calendar.h:1343
Definition bdlt_calendar.h:569
BusinessDayConstIterator endBusinessDays() const
Definition bdlt_calendar.h:1710
BusinessDayConstReverseIterator rendBusinessDays() const
Definition bdlt_calendar.h:1974
bool isInRange(const Date &date) const
Definition bdlt_calendar.h:1824
BusinessDayConstReverseIterator rbeginBusinessDays() const
Definition bdlt_calendar.h:1925
BusinessDayConstIterator beginBusinessDays() const
Definition bdlt_calendar.h:1650
Definition bdlt_date.h:294
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bbldc_basicisma30360.h:112
Definition bdlt_calendarutil.h:173
static int subtractBusinessDaysIfValid(bdlt::Date *result, const bdlt::Date &original, const bdlt::Calendar &calendar, int numBusinessDays)
static int shiftModifiedFollowingIfValid(bdlt::Date *result, const bdlt::Date &original, const bdlt::Calendar &calendar)
static int addBusinessDaysIfValid(bdlt::Date *result, const bdlt::Date &original, const bdlt::Calendar &calendar, int numBusinessDays)
ShiftConvention
Enumeration used to delineate various date-shifting conventions.
Definition bdlt_calendarutil.h:178
@ e_UNADJUSTED
Definition bdlt_calendarutil.h:180
@ e_MODIFIED_PRECEDING
Definition bdlt_calendarutil.h:191
@ e_FOLLOWING
Definition bdlt_calendarutil.h:182
@ e_PRECEDING
Definition bdlt_calendarutil.h:185
@ e_MODIFIED_FOLLOWING
Definition bdlt_calendarutil.h:188
static int shiftIfValid(bdlt::Date *result, const bdlt::Date &original, const bdlt::Calendar &calendar, ShiftConvention convention)
static int nthBusinessDayOfMonthOrMaxIfValid(bdlt::Date *result, const bdlt::Calendar &calendar, int year, int month, int n)
static int shiftIfValid(bdlt::Date *result, const bdlt::Date &original, const bdlt::Calendar &calendar, ShiftConvention convention, bdlt::DayOfWeek::Enum specialDay, bool extendSpecialDay, ShiftConvention specialConvention)
static int shiftFollowingIfValid(bdlt::Date *result, const bdlt::Date &original, const bdlt::Calendar &calendar)
Definition bdlt_calendarutil.h:349
static int shiftPrecedingIfValid(bdlt::Date *result, const bdlt::Date &original, const bdlt::Calendar &calendar)
Definition bdlt_calendarutil.h:380
static int shiftModifiedPrecedingIfValid(bdlt::Date *result, const bdlt::Date &original, const bdlt::Calendar &calendar)
Enum
Enumerated day-of-week values.
Definition bdlt_dayofweek.h:123