BDE 4.39.x 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.
173///
174/// See @ref bdlt_calendarutil
176
177 // TYPES
178
179 /// Enumeration used to delineate various date-shifting conventions.
181
182 e_UNADJUSTED, // The date is not adjusted.
183
184 e_FOLLOWING, // The date is adjusted using
185 // 'shiftFollowingIfValid'.
186
187 e_PRECEDING, // The date is adjusted using
188 // 'shiftPrecedingIfValid'.
189
190 e_MODIFIED_FOLLOWING, // The date is adjusted using
191 // 'shiftModifiedFollowingIfValid'.
192
193 e_MODIFIED_PRECEDING // The date is adjusted using
194 // 'shiftModifiedPrecedingIfValid'.
195 };
196
197 // CLASS METHODS
198
199 /// Load, into the specified `result`, the date that is the specified
200 /// `numBusinessDays` chronologically after the specified `original`
201 /// date according to the specified `calendar`. The resulting date is
202 /// chronologically before the `original` date for negative values of
203 /// `numBusinessDays`, the chronologically earliest business day that is
204 /// on or after the `original` date for `0 == numBusinessDays`, and
205 /// chronologically after the `original` date for positive values of
206 /// `numBusinessDays`. Return 0 on success, and a non-zero value,
207 /// without modifying `*result`, if either the `original` date or the
208 /// resulting date is not within the valid range of `calendar`.
209 ///
210 /// \note Note that if `0 != numBusinessDays`, then the result of
211 /// `addBusinessDaysIfValid(res, orig, cal, numBusinessDays)` is
212 /// identical to the result of
213 /// `subtractBusinessDaysIfValid(res, orig, cal, -numBusinessDays)`.
215 const bdlt::Date& original,
216 const bdlt::Calendar& calendar,
217 int numBusinessDays);
218
219 /// Load, into the specified `result`, the date corresponding to the
220 /// specified `n`th business day of the specified `month` and the
221 /// specified `year` based on the specified `calendar`. A positive
222 /// value of `n` indicates that counting the number of business days
223 /// begins from the first calendar date of the month (inclusive), and a
224 /// negative value of `n` indicates that counting the number of business
225 /// days begins from the last calendar date of the month (inclusive).
226 /// If there are fewer than `abs(n)` business days in the month
227 /// according to the `calendar`, the business day furthest from the
228 /// first date of the month is chosen if `n > 0`, and the business day
229 /// furthest from the last date of the month is chosen if `n < 0`.
230 /// Return 0 on success, and a non-zero value, without modifying
231 /// `*result`, if the entire month specified by `year` and `month` is
232 /// not within the valid range of the `calendar` or there are no
233 /// business days in the month specified by `year` and `month`.
234 ///
235 /// \pre The behavior is undefined unless `n != 0`, `1 <= year <= 9999`, and
236 /// `1 <= month <= 12`.
238 bdlt::Date *result,
239 const bdlt::Calendar& calendar,
240 int year,
241 int month,
242 int n);
243
244 /// Load, into the specified `result`, the date of the chronologically
245 /// earliest business day that is on or after the specified `original`
246 /// date based on the specified `calendar`. Return 0 on success, and a
247 /// non-zero value, without modifying `*result`, if the `original` date
248 /// is not within the valid range of `calendar` or the following
249 /// business day cannot be found within the valid range of `calendar`.
250 static int shiftFollowingIfValid(bdlt::Date *result,
251 const bdlt::Date& original,
252 const bdlt::Calendar& calendar);
253
254 /// Load, into the specified `result`, the date of the business day that
255 /// is derived from the specified `original` date based on the specified
256 /// `calendar` according to the specified date-shifting `convention`.
257 /// Return 0 on success, and a non-zero value, without modifying
258 /// `*result`, if a valid business date cannot be found according to the
259 /// `convention` within the valid range of `calendar`.
260 static int shiftIfValid(bdlt::Date *result,
261 const bdlt::Date& original,
262 const bdlt::Calendar& calendar,
263 ShiftConvention convention);
264
265 /// Load, into the specified `result`, the date of the business day that
266 /// is derived from the specified `original` date based on the specified
267 /// `calendar` according to the specified date-shifting `convention`,
268 /// except when the `original` is either the specified `specialDay` of
269 /// the week, or - if the specified `extendSpecialDay` is `true` - one
270 /// of the (possibly empty) set of contiguous non-business days
271 /// immediately *preceding* a `specialDay` according to the `calendar`,
272 /// in which case the `result` is determined using the specified
273 /// `specialConvention`. Return 0 on success, and a non-zero value,
274 /// without modifying `*result`, if a valid business date cannot be
275 /// found according to the above algorithm within the valid range of `calendar`.
276 ///
277 /// \note Note that this method is useful for computing, for
278 /// example, Korean bond coupon payment dates.
279 static int shiftIfValid(bdlt::Date *result,
280 const bdlt::Date& original,
281 const bdlt::Calendar& calendar,
282 ShiftConvention convention,
283 bdlt::DayOfWeek::Enum specialDay,
284 bool extendSpecialDay,
285 ShiftConvention specialConvention);
286
287 /// Load, into the specified `result`, the date of the chronologically
288 /// earliest business day that is on or after the specified `original`
289 /// date, unless a date cannot be found in the same month, in which case
290 /// load the chronologically latest business day before the `original`
291 /// date based on the specified `calendar`. Return 0 on success, and a
292 /// non-zero value, without modifying `*result`, if the `original` date
293 /// is not within the valid range of `calendar` or a valid business date
294 /// cannot be found according to the above algorithm within the valid
295 /// range of `calendar`.
297 const bdlt::Date& original,
298 const bdlt::Calendar& calendar);
299
300 /// Load, into the specified `result`, the date of the chronologically
301 /// latest business day that is on or before the specified `original`
302 /// date, unless a date cannot be found in the same month, in which case
303 /// load the chronologically earliest business day after the `original`
304 /// date based on the specified `calendar`. Return 0 on success, and a
305 /// non-zero value, without modifying `*result`, if the `original` date
306 /// is not within the valid range of `calendar` or a valid business date
307 /// cannot be found according to the above algorithm within the valid
308 /// range of `calendar`.
310 const bdlt::Date& original,
311 const bdlt::Calendar& calendar);
312
313 /// Load, into the specified `result`, the date of the chronologically
314 /// latest business day that is on or before the specified `original`
315 /// date based on the specified `calendar`. Return 0 on success, and a
316 /// non-zero value, without modifying `*result`, if the `original` date
317 /// is not within the valid range of `calendar` or the preceding
318 /// business day cannot be found within the valid range of `calendar`.
319 static int shiftPrecedingIfValid(bdlt::Date *result,
320 const bdlt::Date& original,
321 const bdlt::Calendar& calendar);
322
323 /// Load, into the specified `result`, the date that is the specified
324 /// `numBusinessDays` chronologically before the specified `original`
325 /// date according to the specified `calendar`. The resulting date is
326 /// chronologically before the `original` date for positive values of
327 /// `numBusinessDays`, the chronologically latest business day that is
328 /// on or before the `original` date for `0 == numBusinessDays`, and
329 /// chronologically after the `original` date for negative values of
330 /// `numBusinessDays`. Return 0 on success, and a non-zero value,
331 /// without modifying `*result`, if either the `original` date or the
332 /// resulting date is not within the valid range of `calendar`.
333 ///
334 /// \note Note that if `0 != numBusinessDays`, then the result of
335 /// `subtractBusinessDaysIfValid(res, orig, cal, numBusinessDays)` is
336 /// identical to the result of
337 /// `addBusinessDaysIfValid(res, orig, cal, -numBusinessDays)`.
339 bdlt::Date *result,
340 const bdlt::Date& original,
341 const bdlt::Calendar& calendar,
342 int numBusinessDays);
343};
344
345// ============================================================================
346// INLINE DEFINITIONS
347// ============================================================================
348
349 // -------------------
350 // struct CalendarUtil
351 // -------------------
352
353// CLASS METHODS
354inline
356 const bdlt::Date& original,
357 const bdlt::Calendar& calendar)
358{
359 BSLS_ASSERT(result);
360
361 enum {
362 e_SUCCESS = 0,
363 e_BAD_INPUT = 1,
364 e_OUT_OF_RANGE = 2,
365 e_NOT_FOUND = 3
366 };
367
368 if (!calendar.isInRange(original)) {
369 return e_BAD_INPUT; // RETURN
370 }
371
373 calendar.beginBusinessDays(original);
374 if (iter != calendar.endBusinessDays()) {
375 *result = *iter;
376 return e_SUCCESS; // RETURN
377 }
378 else {
379 return e_OUT_OF_RANGE; // RETURN
380 }
381
382 return e_NOT_FOUND;
383}
384
385inline
387 const bdlt::Date& original,
388 const bdlt::Calendar& calendar)
389{
390 BSLS_ASSERT(result);
391
392 enum {
393 e_SUCCESS = 0,
394 e_BAD_INPUT = 1,
395 e_OUT_OF_RANGE = 2,
396 e_NOT_FOUND = 3
397 };
398
399 if (!calendar.isInRange(original)) {
400 return e_BAD_INPUT; // RETURN
401 }
402
404 calendar.rbeginBusinessDays(original);
405 if (iter != calendar.rendBusinessDays()) {
406 *result = *iter;
407 return e_SUCCESS; // RETURN
408 }
409 else {
410 return e_OUT_OF_RANGE; // RETURN
411 }
412
413 return e_NOT_FOUND;
414}
415
416} // close package namespace
417
418
419#endif
420
421// ----------------------------------------------------------------------------
422// Copyright 2018 Bloomberg Finance L.P.
423//
424// Licensed under the Apache License, Version 2.0 (the "License");
425// you may not use this file except in compliance with the License.
426// You may obtain a copy of the License at
427//
428// http://www.apache.org/licenses/LICENSE-2.0
429//
430// Unless required by applicable law or agreed to in writing, software
431// distributed under the License is distributed on an "AS IS" BASIS,
432// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
433// See the License for the specific language governing permissions and
434// limitations under the License.
435// ----------------------------- END-OF-FILE ----------------------------------
436
437/** @} */
438/** @} */
439/** @} */
Definition bdlt_calendar.h:1395
Definition bdlt_calendar.h:570
BusinessDayConstIterator endBusinessDays() const
Definition bdlt_calendar.h:1769
BusinessDayConstReverseIterator rendBusinessDays() const
Definition bdlt_calendar.h:2033
bool isInRange(const Date &date) const
Definition bdlt_calendar.h:1883
BusinessDayConstReverseIterator rbeginBusinessDays() const
Definition bdlt_calendar.h:1984
BusinessDayConstIterator beginBusinessDays() const
Definition bdlt_calendar.h:1709
CalendarReverseIteratorAdapter< BusinessDayConstIterator > BusinessDayConstReverseIterator
Definition bdlt_calendar.h:615
Definition bdlt_date.h:294
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bbldc_basicisma30360.h:112
Definition bdlt_calendarutil.h:175
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:180
@ e_UNADJUSTED
Definition bdlt_calendarutil.h:182
@ e_MODIFIED_PRECEDING
Definition bdlt_calendarutil.h:193
@ e_FOLLOWING
Definition bdlt_calendarutil.h:184
@ e_PRECEDING
Definition bdlt_calendarutil.h:187
@ e_MODIFIED_FOLLOWING
Definition bdlt_calendarutil.h:190
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:355
static int shiftPrecedingIfValid(bdlt::Date *result, const bdlt::Date &original, const bdlt::Calendar &calendar)
Definition bdlt_calendarutil.h:386
static int shiftModifiedPrecedingIfValid(bdlt::Date *result, const bdlt::Date &original, const bdlt::Calendar &calendar)
Enum
Enumerated day-of-week values.
Definition bdlt_dayofweek.h:125