BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlt_calendar.h
Go to the documentation of this file.
1/// @file bdlt_calendar.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlt_calendar.h -*-C++-*-
8#ifndef INCLUDED_BDLT_CALENDAR
9#define INCLUDED_BDLT_CALENDAR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlt_calendar bdlt_calendar
15/// @brief Provide fast repository for accessing weekend/holiday information.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlt
19/// @{
20/// @addtogroup bdlt_calendar
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlt_calendar-purpose"> Purpose</a>
25/// * <a href="#bdlt_calendar-classes"> Classes </a>
26/// * <a href="#bdlt_calendar-description"> Description </a>
27/// * <a href="#bdlt_calendar-weekend-days-and-weekend-days-transitions"> Weekend Days and Weekend-Days Transitions </a>
28/// * <a href="#bdlt_calendar-nested-iterators"> Nested Iterators </a>
29/// * <a href="#bdlt_calendar-iterator-invalidation"> Iterator Invalidation </a>
30/// * <a href="#bdlt_calendar-performance-and-exception-safety-guarantees"> Performance and Exception-Safety Guarantees </a>
31/// * <a href="#bdlt_calendar-usage"> Usage </a>
32/// * <a href="#bdlt_calendar-example-1-populating-calendars"> Example 1: Populating Calendars </a>
33/// * <a href="#bdlt_calendar-example-2-using-calendars"> Example 2: Using Calendars </a>
34///
35/// # Purpose {#bdlt_calendar-purpose}
36/// Provide fast repository for accessing weekend/holiday information.
37///
38/// # Classes {#bdlt_calendar-classes}
39///
40/// - bdlt::Calendar: fast repository for accessing weekend/holiday information
41///
42/// @see bdlt_packedcalendar
43///
44/// # Description {#bdlt_calendar-description}
45/// This component provides a value-semantic class,
46/// `bdlt::Calendar`, that represents weekend and holiday information over a
47/// *valid* *range* of dates. A `bdlt::Calendar` is an approximation to the
48/// same *mathematical* type, and is capable of representing the same subset of
49/// *mathematical* values, as a `bdlt::PackedCalendar`. A `bdlt::Calendar`
50/// object (representing the same *mathematical* value) can be constructed
51/// directly from a reference to a non-modifiable `bdlt::PackedCalendar` object,
52/// and a reference to a non-modifiable `bdlt::PackedCalendar` is readily
53/// accessible from any `bdlt::Calendar` object.
54///
55/// But unlike `bdlt::PackedCalendar`, which is optimized for spatial
56/// efficiency, `bdlt::Calendar` is designed to be especially efficient at
57/// determining whether a given `bdlt::Date` value (within the valid range for a
58/// particular `bdlt::Calendar` object) is a business day -- i.e., not a weekend
59/// day or holiday (see "Usage" below). For example, the cost of determining
60/// whether a given `bdlt::Date` is a business day, as opposed to a weekend or
61/// holiday, consists of only a few constant-time operations, compared to a
62/// binary search in a `bdlt::PackedCalendar` representing the same calendar
63/// value.
64///
65/// Default-constructed calendars are empty, and have an empty valid range.
66/// Calendars can also be constructed with an initial (non-empty) valid range,
67/// implying that all dates within that range are business days. The
68/// `setValidRange` and `addDay` methods modify the valid range of a calendar,
69/// and a suite of "add" methods can be used to populate a calendar with
70/// weekend days and holidays.
71///
72/// The `addHolidayCode` method associates an integer "holiday code" with a
73/// specific date, and can be called repeatedly with different integers and the
74/// same date to build up a set of holiday codes for that date. Note that
75/// holiday codes are unique integers that, from the perspective of the
76/// calendar, have no particular meaning. Typically, the user will choose
77/// holiday code values that are indices into an auxiliary collection (such as a
78/// `bsl::vector<bsl::string>`) to identify holiday names for end-user display.
79///
80/// Once a calendar is populated, a rich set of accessor methods can be used to
81/// determine, e.g., if a given date is a business day, or the number of
82/// non-business days within some subrange of the calendar. The holidays
83/// within a calendar can be obtained in increasing (chronological) order using
84/// an iterator identified by the nested `HolidayConstIterator` `typedef`. The
85/// set of holiday codes associated with an arbitrary date in a
86/// `bdlt::Calendar` (or the current holiday referred to by a
87/// `HolidayConstIterator`) can be obtained in increasing (numerical) order
88/// using an iterator identified by the nested `HolidayCodeConstIterator`
89/// `typedef` (see below).
90///
91/// Calendars are value-semantic objects, and, as such, necessarily support all
92/// of the standard value-semantic operations, such as default construction,
93/// copy construction and copy assignment, equality comparison, and
94/// externalization (BDEX streaming, in particular). Calendars also support
95/// the notions of both union and intersection merging operations, whereby a
96/// calendar can change its value to contain the union or intersection of its
97/// own contained weekend days, holidays, and holiday codes with those of
98/// another calendar object. Such merging operations will, in general, also
99/// alter the valid range of the resulting calendar. Note that merged
100/// calendars can be significantly more efficient for certain repeated
101/// "is-common-business-day" determinations among two or more calendars.
102///
103/// ## Weekend Days and Weekend-Days Transitions {#bdlt_calendar-weekend-days-and-weekend-days-transitions}
104///
105///
106/// A calendar maintains a set of dates considered to be weekend days.
107/// Typically, a calendar's weekend days fall on the same days of the week for
108/// the entire range of a calendar. For example, the weekend for United States
109/// has consisted of Saturday and Sunday since the year 1940. The
110/// `addWeekendDay` and `addWeekendDays` methods can be used to specify the
111/// weekend days for these calendars.
112///
113/// However, sometimes a calendar's weekend days changes over time. For
114/// example, Bangladesh's weekend consisted of Friday until June 1, 1997 when
115/// Bangladesh changed its weekends to contain both Friday and Saturday. Later,
116/// on October 1, 2001, Bangladesh reverted to a weekend of only Friday, until
117/// on September 9, 2009, Bangladesh again changed its weekends to include both
118/// Friday and Saturday.
119///
120/// To optimize for space allocation while supporting both consistent and
121/// changing weekend days, a calendar represents weekend information using a
122/// sequence of "weekend-days transitions", each of which comprises a date and a
123/// set of days of the week considered to be the weekend on and after that
124/// date. To represent the weekend days of Bangladesh, a calendar can use a
125/// sequence of four weekend-days transitions: (1) a transition on January 1,
126/// 0001 having a weekend day set containing only Friday, (2) a transition at
127/// June 1, 1997 having a weekend day set containing Friday and Saturday, (3) a
128/// transition at October 1, 2001 having a weekend day set containing only
129/// Friday, and (4) a transition at September 9, 2009 having a weekend day set
130/// containing Friday and Saturday. To represent the weekend days of the United
131/// States, a calendar having a range after 1940 can use a single weekend-days
132/// transition on January 1, 0001 containing Saturday and Sunday.
133///
134/// On construction, a calendar does not contain any weekend-days transitions.
135/// The `addWeekendDaysTransition` method adds a new weekend-days transition or
136/// replaces an existing weekend-days transition. The `addWeekendDay` and
137/// `addWeekendDays` methods create a weekend-days transition at January 1,
138/// 0001, if one doesn't already exist, and update the set of weekend days for
139/// that transition. `addWeekendDay` and `addWeekendDays` should only be used
140/// for calendars having a consistent set of weekend days throughout their
141/// entire range. The use of `addWeekendDay` and `addWeekendDays` is intended
142/// to be *mutually* *exclusive* to the use of `addWeekendDaysTransition`. As
143/// such, the behavior of using these two methods together with
144/// `addWeekendDaysTransition` is undefined.
145///
146/// ## Nested Iterators {#bdlt_calendar-nested-iterators}
147///
148///
149/// Also provided are several STL-style `const` bidirectional iterators
150/// accessible as nested `typedef`s. `HolidayConstIterator`,
151/// `HolidayCodeConstIterator`, `WeekendDaysTransitionConstIterator`, and
152/// `BusinessDayConstIterator`, respectively, iterate over a chronologically
153/// ordered sequence of holidays, a numerically ordered sequence of holiday
154/// codes, a sequence of chronologically ordered weekend-days transitions, and a
155/// sequence of chronologically ordered business days. Reverse iterators are
156/// also provided for each of these (forward) iterators. As a general rule,
157/// calling a `const` method will not invalidate any iterators, and calling a
158/// non-`const` method might invalidate all of them; it is, however, guaranteed
159/// that attempting to add *duplicate* holidays or holiday codes will have no
160/// effect, and therefore will not invalidate any iterators. It is also
161/// guaranteed that adding a new code for an existing holiday will not
162/// invalidate any `HolidayConstIterator` objects.
163///
164/// Note that these iterators do *not* meet the requirements for a
165/// `bsl::forward_iterator` and should not be used in standard algorithms (e.g.,
166/// `bsl::lower_bound`).
167///
168/// ## Iterator Invalidation {#bdlt_calendar-iterator-invalidation}
169///
170///
171/// The modification of a `bdlt::Calendar` will invalidate iterators referring
172/// to the calendar. The following table shows the relationship between a
173/// calendar manipulator and the types of iterators it will invalidate if the
174/// invocation of the manipulator modified the calendar (e.g., using
175/// `addHoliday` with a date that is not currently a holiday in the calendar):
176/// @code
177/// Manipulator Invalidates
178/// -------------------------- --------------------
179/// 'operator=' H HC WDT BD
180/// 'addHoliday' H HC BD
181/// 'addHolidayCode' HC
182/// 'addHolidayCodeIfInRange' HC
183/// 'addHolidayIfInRange' H HC BD
184/// 'addWeekendDay' WDT BD
185/// 'addWeekendDays' WDT BD
186/// 'addWeekendDaysTransition' WDT BD
187/// 'intersectBusinessDays' H HC WDT BD
188/// 'intersectNonBusinessDays' H HC WDT BD
189/// 'removeAll' H HC WDT BD
190/// 'removeHoliday' H HC BD
191/// 'removeHolidayCode' HC
192/// 'setValidRange' H HC BD
193/// 'unionBusinessDays' H HC WDT BD
194/// 'unionNonBusinessDays' H HC WDT BD
195///
196/// where "H" represents the holiday iterators ('HolidayConstIterator' and
197/// 'HolidayConstReverseIterator'), "HC" represents the holiday code iterators
198/// ('HolidayCodeConstIterator' and 'HolidayCodeConstReverseIterator'), "WDT"
199/// represents the weekend-days transition iterators
200/// ('WeekendDaysTransitionConstIterator' and
201/// 'WeekendDaysTransitionConstReverseIterator'), and "BD" represents the
202/// business day iterators ('BusinessDayConstIterator' and
203/// 'BusinessDayConstReverseIterator').
204/// @endcode
205///
206/// ## Performance and Exception-Safety Guarantees {#bdlt_calendar-performance-and-exception-safety-guarantees}
207///
208///
209/// `bdlt::Calendar` supports `O[1]` (i.e., constant-time) determination of
210/// whether a given `bdlt::Date` value is or is not a business day, which is
211/// accomplished by augmenting the implementation of a packed calendar with a
212/// supplementary cache. The invariant that this cache and the data represented
213/// in the underlying `bdlt::PackedCalendar` be maintained in a consistent
214/// state may add significantly to the cost of performing many manipulator
215/// operations, especially those that affect the calendar's valid range and add
216/// a new weekend-days transition. Moreover, the cost of many of these
217/// operations will now be proportional to the length(s) of the valid range(s),
218/// as well as their respective numbers of holidays and associated holiday codes
219/// and weekend-days transitions. Hence, when populating a calendar, it is
220/// recommended that the desired value be captured first as a
221/// `bdlt::PackedCalendar`, which can then be used efficiently to
222/// *value-construct* the desired `bdlt::Calendar` object. See the
223/// component-level doc for @ref bdlt_packedcalendar for its performance
224/// guarantees.
225///
226/// All methods of the `bdlt::Calendar` are exception-safe, but in general
227/// provide only the basic guarantee (i.e., no guarantee of rollback): If an
228/// exception occurs (i.e., while attempting to allocate memory), the calendar
229/// object is left in a coherent state, but (unless otherwise specified) its
230/// *value* is undefined.
231///
232/// ## Usage {#bdlt_calendar-usage}
233///
234///
235/// The two subsections below illustrate various aspects of populating and using
236/// calendars.
237///
238/// ### Example 1: Populating Calendars {#bdlt_calendar-example-1-populating-calendars}
239///
240///
241/// `bdlt::Calendars` can be populated directly, but are often more efficiently
242/// created by first creating a corresponding `bdlt::PackedCalendar`, and then
243/// using that object to construct the calendar. As an example, suppose we
244/// want to provide efficient access to a (high-performance) `bdlt::Calendar`
245/// for a variety of locales, whose raw information comes from, say, a database.
246/// The latency associated with fetching data for individual calendars on
247/// demand from a typical database can be prohibitively expensive, so it may
248/// make sense to acquire data for all calendars in a single query at start-up.
249///
250/// First, we declare a `MyPackedCalendarCache` that, internally, is just a
251/// mapping from (typically short) character string names (such as "NYB",
252/// representing New York Bank settlement days) to `bdlt::PackedCalendar`
253/// objects, containing densely packed calendar data:
254/// @code
255/// /// This class maintains a space-efficient repository of calendar data
256/// /// associated with a (typically short) name.
257/// class MyPackedCalendarCache {
258///
259/// // DATA
260/// bsl::unordered_map<bsl::string, bdlt::PackedCalendar> d_map;
261///
262/// public:
263/// // CREATORS
264///
265/// /// Create an empty `MyPackedCalendarCache`. Optionally specify a
266/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
267/// /// 0, the currently installed default allocator is used.
268/// MyPackedCalendarCache(bslma::Allocator *basicAllocator = 0);
269///
270/// // MANIPULATORS
271///
272/// /// Associate the value of the specified `calendar` with the
273/// /// specified `name`.
274/// void assign(const bsl::string& name,
275/// const bdlt::PackedCalendar& calendar);
276///
277/// // ACCESSORS
278///
279/// /// Return the address of calendar data associated with the
280/// /// specified `name`, or 0 if no such association exists.
281/// const bdlt::PackedCalendar *lookup(const bsl::string& name) const;
282/// };
283///
284/// // CREATORS
285/// MyPackedCalendarCache::MyPackedCalendarCache(
286/// bslma::Allocator *basicAllocator)
287/// : d_map(basicAllocator)
288/// {
289/// }
290///
291/// // MANIPULATORS
292/// void MyPackedCalendarCache::assign(const bsl::string& name,
293/// const bdlt::PackedCalendar& calendar)
294/// {
295/// d_map[name] = calendar;
296/// }
297///
298/// // ACCESSORS
299/// const bdlt::PackedCalendar *MyPackedCalendarCache::lookup(
300/// const bsl::string& name) const
301/// {
302/// typedef bsl::unordered_map<bsl::string, bdlt::PackedCalendar> Cache;
303/// Cache::const_iterator iter = d_map.find(name);
304///
305/// if (iter == d_map.end()) {
306/// return 0; // RETURN
307/// }
308/// return &iter->second;
309/// }
310/// @endcode
311/// Then, we define an application function, `loadMyPackedCalendarCache`, that
312/// takes the address of a `MyPackedCalendarCache` and populates it with
313/// up-to-date calendar data for all known locales (which, in the future, will
314/// be from a well-known database location):
315/// @code
316/// /// Load, into the specified `result`, up-to-date calendar information
317/// /// for every known locale. Return 0 on success, and a non-zero value
318/// /// otherwise.
319/// int loadMyPackedCalendarCache(MyPackedCalendarCache *result)
320/// {
321/// bdlt::PackedCalendar calendar;
322/// calendar.setValidRange(bdlt::Date(2000, 1, 1),
323/// bdlt::Date(2020, 12, 31));
324/// result->assign("NYB", calendar);
325/// return 0;
326/// }
327/// @endcode
328/// We can imagine that there might be dozens, even hundreds of different
329/// locales, and that most applications will not need efficient access to
330/// calendar data from many, let alone every locale; however, many long-running
331/// applications may well need to obtain efficient access to the same calendar
332/// data repeatedly.
333///
334/// Next, we create a second-level of cache, `MyCalendarCache`, that maintains
335/// a repository of the more runtime-efficient, but also more space-intensive,
336/// `bdlt::Calendar` objects, which are instantiated on demand from a
337/// packed-calendar-based data source:
338/// @code
339/// /// This class maintains a cache of runtime-efficient calendar objects
340/// /// created on demand from a compact packed-calendar-based data source,
341/// /// whose address is supplied at construction.
342/// class MyCalendarCache {
343///
344/// // DATA
345/// MyPackedCalendarCache *d_datasource_p;
346/// bsl::unordered_map<bsl::string, bdlt::Calendar> d_map;
347///
348/// public:
349/// // CREATORS
350///
351/// /// Create an empty `MyCalendarCache` associated with the specified
352/// /// `dataSource`. Optionally specify a `basicAllocator` used to
353/// /// supply memory. If `basicAllocator` is 0, the currently
354/// /// installed default allocator is used.
355/// MyCalendarCache(MyPackedCalendarCache *dataSource,
356/// bslma::Allocator *basicAllocator = 0);
357///
358/// // MANIPULATORS
359///
360/// /// Return the address of calendar data associated with the
361/// /// specified `name`, or 0 if no such association exists in the data
362/// /// source whose address was supplied at construction. Note that
363/// /// this method may alter the physical state of this object (and is
364/// /// therefore deliberately declared non-`const`).
365/// const bdlt::Calendar *lookup(const bsl::string& name);
366/// };
367///
368/// MyCalendarCache::MyCalendarCache(MyPackedCalendarCache *dataSource,
369/// bslma::Allocator *basicAllocator)
370/// : d_datasource_p(dataSource)
371/// , d_map(basicAllocator)
372/// {
373/// }
374///
375/// const bdlt::Calendar *MyCalendarCache::lookup(const bsl::string& name)
376/// {
377/// typedef bsl::unordered_map<bsl::string, bdlt::Calendar> Cache;
378/// Cache::const_iterator iter = d_map.find(name);
379/// if (iter == d_map.end()) {
380/// const bdlt::PackedCalendar *pc = d_datasource_p->lookup(name);
381/// if (!pc) {
382///
383/// // No such name in the data source.
384///
385/// return 0; // RETURN
386/// }
387///
388/// // Create new entry in calendar cache.
389///
390/// iter = d_map.insert(bsl::make_pair(name, *pc)).first;
391/// }
392///
393/// // An efficient calendar either already existed or was created.
394///
395/// return &iter->second;
396/// }
397/// @endcode
398/// Now, we can create and populate the cache:
399/// @code
400/// MyPackedCalendarCache packedCalendarCache;
401/// MyCalendarCache calendarCache(&packedCalendarCache);
402///
403/// loadMyPackedCalendarCache(&packedCalendarCache);
404/// @endcode
405/// Finally, we request the "NYB" calendar and verify the returned value:
406/// @code
407/// const bdlt::Calendar *calendarPtr = calendarCache.lookup("NYB");
408///
409/// assert(calendarPtr->firstDate() == bdlt::Date(2000, 1, 1));
410/// assert(calendarPtr->lastDate() == bdlt::Date(2020, 12, 31));
411/// @endcode
412///
413/// ### Example 2: Using Calendars {#bdlt_calendar-example-2-using-calendars}
414///
415///
416/// What makes a `bdlt::Calendar` substantially different from a
417/// `bdlt::PackedCalendar` is the speed with which the `bdlt::Calendar` can
418/// report whether a given date is or is not a business day. An important use
419/// of high-performance calendar objects in financial applications is to quickly
420/// determine the settlement date of a financial instrument. In some
421/// applications (e.g., those that explore the cross product of various
422/// portfolios over several horizons and scenarios), the settlement date may
423/// need to be calculated literally billions of times. The settlement date
424/// will often be determined from a periodic target date, such as the 15th or
425/// 30th of the month, which is then perturbed in some way to arrive at a valid
426/// settlement date.
427///
428/// One very common algorithm a security may prescribe for finding a valid
429/// settlement date is known as *modified* *following*: Given a target day, the
430/// settlement date for that month is defined as the first valid business day
431/// at or after the given target day in the same month; if no such date exists,
432/// then the settlement date is the closest valid business day before the target
433/// day in that month.
434///
435/// First, we create a `struct`, `MyCalendarUtil`, that provides the
436/// `modifiedFollowing` method:
437/// @code
438/// struct MyCalendarUtil {
439///
440/// // CLASS METHODS
441///
442/// // Return the date of the first business day at or after the
443/// // specified `targetDay` in the specified `month` and `year`
444/// // according to the specified `calendar`, unless the resulting
445/// // date would not fall within `month`, in which case return
446/// // instead the date of the first business day before `targetDay`
447/// // in `month`. The behavior is undefined unless all candidate
448/// // dates applied to `calendar` are within its valid range and
449/// // there exists at least one business day within `month`.
450/// static bdlt::Date modifiedFollowing(int targetDay,
451/// int month,
452/// int year,
453/// const bdlt::Calendar& calendar)
454/// {
455/// BSLS_ASSERT(bdlt::Date::isValidYearMonthDay(year,
456/// month,
457/// targetDay));
458///
459/// // Efficiency is important so we will minimize the number of
460/// // conversions between year/month/day and 'bdlt::Date' objects.
461///
462/// bdlt::Date date(year, month, targetDay);
463///
464/// if (0 == calendar.getNextBusinessDay(&date, date - 1)
465/// && month == date.month()) {
466/// return date; // RETURN
467/// }
468/// while (calendar.isNonBusinessDay(--date)) {
469/// // empty
470/// }
471/// return date;
472/// }
473/// };
474/// @endcode
475/// Then, we create and populate two calendars, `cal1` and `cal2`, for testing
476/// the `modifiedFollowing` method:
477/// @code
478/// bdlt::Calendar cal1(bdlt::Date(2015, 1, 1), bdlt::Date(2015,12, 31));
479/// cal1.addWeekendDay(bdlt::DayOfWeek::e_SUN);
480/// cal1.addWeekendDay(bdlt::DayOfWeek::e_SAT);
481/// cal1.addHoliday(bdlt::Date(2015, 7, 3));
482///
483/// bdlt::Calendar cal2(cal1);
484/// cal2.addHoliday(bdlt::Date(2015, 7, 31));
485/// @endcode
486/// Finally, we verify the `modifiedFollowing` functionality:
487/// @code
488/// assert(bdlt::Date(2015, 7, 2) ==
489/// MyCalendarUtil::modifiedFollowing( 2, 7, 2015, cal1));
490/// assert(bdlt::Date(2015, 7, 6) ==
491/// MyCalendarUtil::modifiedFollowing( 3, 7, 2015, cal1));
492/// assert(bdlt::Date(2015, 7, 31) ==
493/// MyCalendarUtil::modifiedFollowing(31, 7, 2015, cal1));
494///
495/// assert(bdlt::Date(2015, 7, 2) ==
496/// MyCalendarUtil::modifiedFollowing( 2, 7, 2015, cal2));
497/// assert(bdlt::Date(2015, 7, 6) ==
498/// MyCalendarUtil::modifiedFollowing( 3, 7, 2015, cal2));
499/// assert(bdlt::Date(2015, 7, 30) ==
500/// MyCalendarUtil::modifiedFollowing(31, 7, 2015, cal2));
501/// @endcode
502/// @}
503/** @} */
504/** @} */
505
506/** @addtogroup bdl
507 * @{
508 */
509/** @addtogroup bdlt
510 * @{
511 */
512/** @addtogroup bdlt_calendar
513 * @{
514 */
515
516#include <bdlscm_version.h>
517
519#include <bdlt_date.h>
520#include <bdlt_dayofweek.h>
521#include <bdlt_dayofweekset.h>
522#include <bdlt_packedcalendar.h>
523
524#include <bdlc_bitarray.h>
525
526#include <bslalg_swaputil.h>
527
528#include <bslh_hash.h>
529
530#include <bslma_allocator.h>
532
534
535#include <bsls_assert.h>
536#include <bsls_preconditions.h>
537#include <bsls_review.h>
538
539#include <bsl_iosfwd.h>
540#include <bsl_iterator.h>
541
542
543namespace bdlt {
544
545class Calendar_BusinessDayConstIter;
546
547 // ==============
548 // class Calendar
549 // ==============
550
551/// This class implements a runtime-efficient, value-semantic repository of
552/// weekend and holiday information over a *valid* *range* of dates. This
553/// valid range, `[firstDate() .. lastDate()]`, spans the first and last
554/// dates of a calendar's accessible contents. A calendar can be
555/// "populated" with weekend and holiday information via a suite of "add"
556/// methods. Any subset of days of the week may be specified as weekend
557/// (i.e., recurring non-business) days starting from a specified date by
558/// adding a weekend-days transition; holidays within the valid range are
559/// specified individually. When adding a holiday, an arbitrary integer
560/// "holiday code" may be associated with that date. Additional holiday
561/// codes for that date may subsequently be added. Both the holidays and
562/// the set of unique holiday codes associated with each holiday date are maintained (internally) in order of increasing value.
563///
564/// \note Note that the
565/// behavior of requesting *any* calendar information for a supplied date
566/// whose value is outside the current *valid* *range* for that calendar
567/// (unless otherwise noted, e.g., `isWeekendDay`) is undefined.
568///
569/// See @ref bdlt_calendar
570class Calendar {
571
572 // DATA
573 PackedCalendar d_packedCalendar;
574 // the packed calendar object, which contains
575 // the weekend day and holiday information
576
577 bdlc::BitArray d_nonBusinessDays;
578 // cache of non-business days; note that the end
579 // of the valid range is defined by
580 // 'd_packedCalendar.firstDate() + length() - 1'
581
582 // FRIENDS
583 friend bool operator==(const Calendar&, const Calendar&);
584 friend bool operator!=(const Calendar&, const Calendar&);
585 template <class HASHALG>
586 friend void hashAppend(HASHALG& hashAlg, const Calendar&);
587
588 private:
589 // PRIVATE MANIPULATORS
590
591 /// Synchronize this calendar's cache by first clearing the cache, then
592 /// repopulating it with the holiday and weekend information from this calendar's `d_packedCalendar`.
593 ///
594 /// \note Note that this method is only
595 /// **exception-neutral**; exception safety and rollback must be
596 /// handled by the caller.
597 void synchronizeCache();
598
599 // PRIVATE ACCESSORS
600
601 /// Return `true` if this calendar's cache correctly represents the
602 /// holiday and weekend information stored in this calendar's
603 /// `d_packedCalendar`, and `false` otherwise.
604 bool isCacheSynchronized() const;
605
606 public:
607 // TYPES
609
611
613
616
619
622
624
627
630
631 // CLASS METHODS
632
633 // Aspects
634
635 /// Return the maximum valid BDEX format version, as indicated by the
636 /// specified `versionSelector`, to be passed to the `bdexStreamOut` method.
637 ///
638 /// \note Note that it is highly recommended that `versionSelector`
639 /// be formatted as "YYYYMMDD", a date representation. Also note that
640 /// `versionSelector` should be a *compile*-time-chosen value that
641 /// selects a format version supported by both externalizer and
642 /// unexternalizer. See the `bslx` package-level documentation for more
643 /// information on BDEX streaming of value-semantic types and
644 /// containers.
645 static int maxSupportedBdexVersion(int versionSelector);
646
647 // CREATORS
648
649 /// Create an empty calendar, i.e., a calendar having an empty valid
650 /// range. Optionally specify a `basicAllocator` used to supply memory.
651 /// If `basicAllocator` is 0, the currently installed default allocator
652 /// is used.
653 explicit Calendar(bslma::Allocator *basicAllocator = 0);
654
655 /// Create a calendar having a valid range from the specified
656 /// `firstDate` through the specified `lastDate`. Optionally specify a
657 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
658 /// the currently installed default allocator is used.
659 ///
660 /// \pre The behavior is undefined unless `firstDate <= lastDate`.
662 const Date& lastDate,
663 bslma::Allocator *basicAllocator = 0);
664
665 /// Create a calendar having the same value as the specified
666 /// `packedCalendar`. Optionally specify a `basicAllocator` used to
667 /// supply memory. If `basicAllocator` is 0, the currently installed
668 /// default allocator is used.
670 bslma::Allocator *basicAllocator = 0);
671
672 /// Create a calendar having the value of the specified `original`
673 /// calendar. Optionally specify a `basicAllocator` used to supply
674 /// memory. If `basicAllocator` is 0, the currently installed default
675 /// allocator is used.
676 Calendar(const Calendar& original, bslma::Allocator *basicAllocator = 0);
677
678 /// Destroy this object.
680
681 // MANIPULATORS
682
683 /// Assign to this calendar the value of the specified `rhs` calendar,
684 /// and return a reference providing modifiable access to this calendar.
685 /// See {Iterator Invalidation} for information regarding which
686 /// iterators are affected by the use of these methods.
687 Calendar& operator=(const Calendar& rhs);
688 Calendar& operator=(const PackedCalendar& rhs);
689
690 /// Extend the valid range (if necessary) of this calendar to include
691 /// the specified `date` value.
692 void addDay(const Date& date);
693
694 /// Mark the specified `date` as a holiday (i.e., a non-business day)
695 /// in this calendar. Extend the valid range of this calendar if
696 /// necessary. If `date` is already marked as a holiday, this method
697 /// has no effect. See {Iterator Invalidation} for information
698 /// regarding which iterators are affected by the use of this method.
699 void addHoliday(const Date& date);
700
701 /// Mark the specified `date` as a holiday (i.e., a non-business day) in
702 /// this calendar and add the specified `holidayCode` (if not already
703 /// present) to the ordered set of codes associated with `date`.
704 /// Extend the valid range of this calendar if necessary. If
705 /// `holidayCode` is already a code for `date`, this method has no
706 /// effect. See {Iterator Invalidation} for information regarding
707 /// which iterators are affected by the use of this method.
708 ///
709 /// \note Note that this method may be called repeatedly with the same value for `date`
710 /// to build up a set of holiday codes for that date.
711 void addHolidayCode(const Date& date, int holidayCode);
712
713 /// Mark the specified `date` as a holiday (i.e., a non-business day)
714 /// in this calendar and add the specified `holidayCode` (if not
715 /// already present) to the set of codes associated with `date`, if
716 /// `date` is within the valid range of this calendar. Return 0 if
717 /// `date` is in range, and a non-zero value otherwise. If
718 /// `holidayCode` is already a code for `date`, or if `date` is not in
719 /// the valid range, this method has no effect. See
720 /// {Iterator Invalidation} for information regarding which iterators are affected by the use of this method.
721 ///
722 /// \note Note that this method may,
723 /// at the expense of verifying `isInRange(date)` for each invocation,
724 /// be called repeatedly with the same value for `date` to build up a
725 /// set of holiday codes for that date.
726 int addHolidayCodeIfInRange(const Date& date, int holidayCode);
727
728 /// Mark the specified `date` as a holiday (i.e., a non-business day) in
729 /// this calendar if `date` is within the valid range. Return 0 if
730 /// `date` is in range, and a non-zero value otherwise. This method has
731 /// no effect if `date` is already marked as a holiday or is not in the
732 /// valid range. See {Iterator Invalidation} for information regarding
733 /// which iterators are affected by the use of this method.
734 int addHolidayIfInRange(const Date& date);
735
736 /// Add the specified `weekendDay` to the set of weekend days associated
737 /// with the weekend-days transition at January 1, 0001 maintained by
738 /// this calendar. Create a transition at January 1, 0001 if one does
739 /// not exist. See {Iterator Invalidation} for information regarding
740 /// which iterators are affected by the use of this method.
741 ///
742 /// \pre The behavior is undefined unless no weekend-days transitions were added
743 /// to this calendar via the `addWeekendDaysTransition` method.
745
746 /// Add the specified `weekendDays` to the set of weekend days
747 /// associated with the weekend-days transition at January 1, 0001
748 /// maintained by this calendar. Create a transition at January 1, 0001
749 /// if one does not exist. See {Iterator Invalidation} for information
750 /// regarding which iterators are affected by the use of this method.
751 ///
752 /// \pre The behavior is undefined unless no weekend-days transitions were
753 /// added to this calendar via the `addWeekendDaysTransition` method.
754 void addWeekendDays(const DayOfWeekSet& weekendDays);
755
756 /// Add to this calendar a weekend-days transition on the specified
757 /// `startDate` having the specified `weekendDays` set. If a
758 /// weekend-days transition already exists on `startDate`, replace the
759 /// set of weekend days of that transition with `weekendDays`. See
760 /// {Iterator Invalidation} for information regarding which iterators are affected by the use of this method.
761 ///
762 /// \note Note that this method does
763 /// not extend the valid range of the calendar.
764 void addWeekendDaysTransition(const Date& startDate,
765 const DayOfWeekSet& weekendDays);
766
767 /// Merge the specified `other` calendar into this calendar such that
768 /// the valid range of this calendar becomes the *intersection* of the
769 /// two calendars' ranges, and the weekend days and holidays for this
770 /// calendar become the union of those (non-business) days from the two
771 /// calendars -- i.e., the valid business days of this calendar become
772 /// the intersection of those of the two original calendar values over
773 /// the *intersection* of their ranges. For each holiday that remains,
774 /// the resulting holiday codes in this calendar will be the union of
775 /// the corresponding original holiday codes. See
776 /// {Iterator Invalidation} for information regarding which iterators
777 /// are affected by the use of this method.
778 void intersectBusinessDays(const Calendar& other);
779 void intersectBusinessDays(const PackedCalendar& other);
780
781 /// Merge the specified `other` calendar into this calendar such that
782 /// the valid range of this calendar becomes the *intersection* of the
783 /// two calendars' ranges, the weekend days for this calendar become the
784 /// intersection of those days from the two calendars, and the holidays
785 /// for this calendar become the set of days that are a holiday in one
786 /// of the calendars and a non-business day in the other calendar --
787 /// i.e., the valid business days of this calendar become the union of
788 /// those of the two original calendars over the *intersection* of their
789 /// ranges. For each holiday that remains, the resulting holiday codes
790 /// in this calendar will be the union of the corresponding original
791 /// holiday codes. See {Iterator Invalidation} for information
792 /// regarding which iterators are affected by the use of this method.
793 void intersectNonBusinessDays(const Calendar& other);
794 void intersectNonBusinessDays(const PackedCalendar& other);
795
796 /// Remove all information from this calendar, leaving it with its
797 /// default constructed "empty" value. See {Iterator Invalidation} for
798 /// information regarding which iterators are affected by the use of
799 /// this method.
800 void removeAll();
801
802 /// Remove from this calendar the holiday having the specified `date` if
803 /// such a holiday exists. This operation has no effect if `date` is
804 /// not a holiday in this calendar. See {Iterator Invalidation} for
805 /// information regarding which iterators are affected by the use of this method.
806 ///
807 /// \note Note that this method is defined for all `date`
808 /// values, not just those that fall within the valid range, and may be
809 /// invoked even on an empty calendar (i.e., having `0 == length()`).
810 void removeHoliday(const Date& date);
811
812 /// Remove from this calendar the specified `holidayCode` for the
813 /// holiday having the specified `date` if such a holiday having
814 /// `holidayCode` exists. This operation has no effect if `date` is not
815 /// a holiday in this calendar, or if the holiday at `date` does not
816 /// have `holidayCode` associated with it. See {Iterator Invalidation}
817 /// for information regarding which iterators are affected by the use of this method.
818 ///
819 /// \note Note that this method is defined for all `date`
820 /// values, not just those that fall within the valid range, and may be
821 /// invoked even on an empty calendar (i.e., having `0 == length()`).
822 void removeHolidayCode(const Date& date, int holidayCode);
823
824 /// Reserve enough space to store at least the specified `numHolidays`
825 /// within this calendar. This method has no effect if
826 /// `numHolidays <= numHolidays()`.
828
829 /// Reserve enough space to store at least the specified
830 /// `numHolidayCodes` within this calendar assuming no additional
831 /// holidays are added to this calendar. This method has no effect if
832 /// `numHolidayCodes <= numHolidayCodesTotal()`.
834
835 /// Set the range of this calendar using the specified `firstDate` and
836 /// `lastDate` as, respectively, the first date and the last date of the
837 /// calendar. Any holiday that is outside the new range and its holiday
838 /// codes are removed. See {Iterator Invalidation} for information
839 /// regarding which iterators are affected by the use of this method.
840 ///
841 /// \pre The behavior is undefined unless `firstDate <= lastDate`.
842 void setValidRange(const Date& firstDate, const Date& lastDate);
843
844 /// Merge the specified `other` calendar into this calendar such that
845 /// the valid range of this calendar becomes the *union* of the two
846 /// calendars' ranges (or the minimal continuous range spanning the two
847 /// ranges, if the ranges are non-overlapping), the weekend days for
848 /// this calendar become the intersection of those days from the two
849 /// calendars, and the holidays for this calendar become the set of days
850 /// that are a holiday in one of the calendars and a non-business day in
851 /// the other calendar -- i.e., the valid business days of this calendar
852 /// become the union of those of the two original calendar values. For
853 /// each holiday that remains, the resulting holiday codes in this
854 /// calendar will be the union of the corresponding original holiday
855 /// codes. See {Iterator Invalidation} for information regarding which
856 /// iterators are affected by the use of this method.
857 void unionBusinessDays(const Calendar& other);
859
860 /// Merge the specified `other` calendar into this calendar such that
861 /// the valid range of this calendar becomes the *union* of the two
862 /// calendars' ranges (or the minimal continuous range spanning the two
863 /// ranges, if the ranges are non-overlapping), and the weekend days
864 /// and holidays for this calendar become the union of those
865 /// (non-business) days from the two calendars -- i.e., the valid
866 /// business days of this calendar become the intersection of those of
867 /// the two calendars after each range is extended to cover the
868 /// resulting one. For each holiday in either calendar, the resulting
869 /// holiday codes in this calendar will be the union of the
870 /// corresponding original holiday codes. See {Iterator Invalidation}
871 /// for information regarding which iterators are affected by the use of
872 /// this method.
873 void unionNonBusinessDays(const Calendar& other);
875
876 // Aspects
877
878 /// Assign to this object the value read from the specified input
879 /// `stream` using the specified `version` format and return a reference
880 /// to the modifiable `stream`. If `stream` is initially invalid, this
881 /// operation has no effect. If `stream` becomes invalid during this
882 /// operation or if `version` is not supported, this object is unaltered.
883 ///
884 /// \note Note that no version is read from `stream`. See the
885 /// `bslx` package-level documentation for more information on BDEX
886 /// streaming of value-semantic types and containers.
887 template <class STREAM>
888 STREAM& bdexStreamIn(STREAM& stream, int version);
889
890 /// Efficiently exchange the value of this object with the value of the
891 /// specified `other` object. This method provides the no-throw exception-safety guarantee.
892 ///
893 /// \pre The behavior is undefined unless this
894 /// object was created with the same allocator as `other`.
895 void swap(Calendar& other);
896
897 // ACCESSORS
898
899 /// Return an iterator providing non-modifiable access to the first
900 /// business day in this calendar. If this calendar has no valid
901 /// business days, the returned iterator has the same value as that
902 /// returned by `endBusinessDays()`.
904
905 /// Return an iterator providing non-modifiable access to the first
906 /// business day that occurs on or after the specified `date` in this
907 /// calendar. If this calendar has no such business day, the returned
908 /// iterator has the same value as that returned by `endBusinessDays(date)`.
909 ///
910 /// \pre The behavior is undefined unless `date` is
911 /// within the valid range of this calendar.
913
914 /// Return an iterator providing non-modifiable access to the first
915 /// holiday code for the specified `date` in this calendar. If there is
916 /// no holiday code associated with `date`, the returned iterator has
917 /// the same value as that returned by `endHolidayCodes(date)`.
918 ///
919 /// \pre The behavior is undefined unless `date` is marked as a holiday in this
920 /// calendar.
922
923 /// Return an iterator providing non-modifiable access to the first
924 /// holiday code for the holiday referenced by the specified `iter`. If
925 /// there is no holiday code associated with the date referenced by
926 /// `iter`, the returned iterator has the same value as that returned by `endHolidayCodes(iter)`.
927 ///
928 /// \pre The behavior is undefined unless `iter`
929 /// refers to a valid holiday of this calendar.
931 const HolidayConstIterator& iter) const;
932
933 /// Return an iterator providing non-modifiable access to the first
934 /// holiday in this calendar. If this calendar has no holidays, the
935 /// returned iterator has the same value as that returned by
936 /// `endHolidays()`.
938
939 /// Return an iterator providing non-modifiable access to the first
940 /// holiday that occurs on or after the specified `date` in this
941 /// calendar. If this calendar has no such holiday, the returned
942 /// iterator has the same value as that returned by `endHolidays(date)`.
943 ///
944 /// \pre The behavior is undefined unless `date` is within the valid range
945 /// of this calendar.
946 HolidayConstIterator beginHolidays(const Date& date) const;
947
948 /// Return an iterator providing non-modifiable access to the first
949 /// weekend-days transition in the chronological sequence of
950 /// weekend-days transitions maintained by this calendar. If this
951 /// calendar has no weekend-days transitions, the returned iterator has
952 /// the same value as that returned by `endWeekendDaysTransitions()`.
954
955 /// Return an iterator providing non-modifiable access to the
956 /// past-the-end business day in this calendar.
958
959 /// Return an iterator providing non-modifiable access to the first
960 /// business day that occurs after the specified `date` in this
961 /// calendar. If this calendar has no such business day, the returned
962 /// iterator has the same value as that returned by `endBusinessDays()`.
963 ///
964 /// \pre The behavior is undefined unless `date` is
965 /// within the valid range of this calendar.
967
968 /// Return an iterator providing non-modifiable access to the
969 /// past-the-end holiday code associated with the specified `date`.
970 ///
971 /// \pre The behavior is undefined unless `date` is marked as a holiday in this
972 /// calendar.
974
975 /// Return an iterator providing non-modifiable access to the
976 /// past-the-end holiday code associated with the date referenced by the specified `iter`.
977 ///
978 /// \pre The behavior is undefined unless `iter`
979 /// references a valid holiday in this calendar.
981 endHolidayCodes(const HolidayConstIterator& iter) const;
982
983 /// Return an iterator providing non-modifiable access to the
984 /// past-the-end holiday in the chronological sequence of holidays
985 /// maintained by this calendar.
987
988 /// Return an iterator providing non-modifiable access to the first
989 /// holiday that occurs after the specified `date` in this calendar.
990 /// If this calendar has no such holiday, the returned iterator has the
991 /// same value as that returned by `endHolidays()`.
992 ///
993 /// \pre The behavior is undefined unless `date` is within the valid range of this calendar.
994 HolidayConstIterator endHolidays(const Date& date) const;
995
996 /// Return an iterator providing non-modifiable access to the
997 /// past-the-end weekend-days transition in the chronological sequence
998 /// of weekend-days transitions maintained by this calendar.
1000
1001 /// Return a reference providing non-modifiable access to the earliest
1002 /// date in the valid range of this calendar.
1003 ///
1004 /// \pre The behavior is undefined unless this calendar is non-empty -- i.e., unless
1005 /// `1 <= length()`.
1006 const Date& firstDate() const;
1007
1008 /// Load, into the specified `nextBusinessDay`, the date of the first
1009 /// business day in this calendar following the specified `date`.
1010 /// Return 0 on success -- i.e., if such a business day exists, and a
1011 /// non-zero value (with no effect on `nextBusinessDay`) otherwise.
1012 ///
1013 /// \pre The behavior is undefined unless `date + 1` is both a valid `bdlt::Date`
1014 /// and within the valid range of this calendar.
1015 int getNextBusinessDay(Date *nextBusinessDay, const Date& date) const;
1016
1017 /// Load, into the specified `nextBusinessDay`, the date of the
1018 /// specified `nth` business day in this calendar following the
1019 /// specified `date`. Return 0 on success -- i.e., if such a business
1020 /// day exists, and a non-zero value (with no effect on `nextBusinessDay`) otherwise.
1021 ///
1022 /// \pre The behavior is undefined unless
1023 /// `date + 1` is both a valid `bdlt::Date` and within the valid range
1024 /// of this calendar, and `0 < nth`.
1025 int getNextBusinessDay(Date *nextBusinessDay,
1026 const Date& date,
1027 int nth) const;
1028
1029 /// Return the holiday at the specified `index` in this calendar. For
1030 /// all `index` values from 0 to `numHolidays() - 1` (inclusive), a
1031 /// unique holiday is returned. The mapping of `index` to holiday is
1032 /// invalidated when the set of holidays is modified by an invocation of
1033 /// `addHoliday`, `addHolidayIfInRange`, `intersectBusinessDays`,
1034 /// `intersectNonBusinessDays`, `removeAll`, `removeHoliday`,
1035 /// `setValidRange`, `unionBusinessDays`, or `unionNonBusinessDays`.
1036 ///
1037 /// \pre The behavior is undefined unless `0 <= index < numHolidays()`.
1038 Date holiday(int index) const;
1039
1040 /// Return, for the holiday at the specified `date` in this calendar,
1041 /// the holiday code at the specified `index`. For all `index` values
1042 /// from 0 to `numHolidayCodes(date) - 1` (inclusive), a unique holiday
1043 /// code is returned. The mapping of `index` to holiday code is
1044 /// invalidated when the set of holidays or holiday codes is modified by
1045 /// an invocation of `addHoliday`, `addHolidayCode`,
1046 /// `addHolidayCodeIfInRange`, `addHolidayIfInRange`,
1047 /// `intersectBusinessDays`, `intersectNonBusinessDays`, `removeAll`,
1048 /// `removeHoliday`, `removeHolidayCode`, `setValidRange`,
1049 /// `unionBusinessDays`, or `unionNonBusinessDays`.
1050 ///
1051 /// \pre The behavior is undefined unless `date` is a holiday in this calendar and `0 <= index < numHolidayCodes(date)`.
1052 ///
1053 /// \note Note that this method
1054 /// facilitates testing and generally should not be used by clients; in
1055 /// particular, using this method to iterate over the holiday codes for
1056 /// `date` is less efficient than using a `HolidayCodeConstIterator`.
1057 int holidayCode(const Date& date, int index) const;
1058
1059 /// Return `true` if the specified `date` is a business day (i.e., not
1060 /// a holiday or weekend day) in this calendar, and `false` otherwise.
1061 ///
1062 /// \pre The behavior is undefined unless `date` is within the valid range of
1063 /// this calendar.
1064 bool isBusinessDay(const Date& date) const;
1065
1066 /// Return `true` if the specified `date` is a holiday in this calendar, and `false` otherwise.
1067 ///
1068 /// \pre The behavior is undefined unless `date` is
1069 /// within the valid range of this calendar.
1070 bool isHoliday(const Date& date) const;
1071
1072 /// Return `true` if the specified `date` is within the valid range of
1073 /// this calendar (i.e., `firstDate() <= date <= lastDate()`), and `false` otherwise.
1074 ///
1075 /// \note Note that the valid range for a `Calendar` is
1076 /// empty if its length is 0.
1077 bool isInRange(const Date& date) const;
1078
1079 /// Return `true` if the specified `date` is not a business day (i.e.,
1080 /// is either a holiday or weekend day) in this calendar, and `false` otherwise.
1081 ///
1082 /// \pre The behavior is undefined unless `date` is within the
1083 /// valid range of this calendar. Note that:
1084 /// @code
1085 /// !isBusinessDay(date)
1086 /// @endcode
1087 /// returns the same result.
1088 bool isNonBusinessDay(const Date& date) const;
1089
1090 /// Return `true` if the specified `date` falls on a day of the week
1091 /// that is considered a weekend day in this calendar, and `false` otherwise.
1092 ///
1093 /// \note Note that this method is defined for all `date` values,
1094 /// not just those that fall within the valid range, and may be invoked
1095 /// even on an empty calendar (i.e., having `0 == length()`).
1096 bool isWeekendDay(const Date& date) const;
1097
1098 /// Return `true` if the specified `dayOfWeek` is a weekend day in this calendar, and `false` otherwise.
1099 ///
1100 /// \pre The behavior is undefined unless
1101 /// no weekend-days transitions were added to this calendar via the
1102 /// `addWeekendDaysTransition` method.
1103 bool isWeekendDay(DayOfWeek::Enum dayOfWeek) const;
1104
1105 /// Return a reference providing non-modifiable access to the latest
1106 /// date in the valid range of this calendar.
1107 ///
1108 /// \pre The behavior is undefined unless this calendar is non-empty -- i.e., unless
1109 /// `1 <= length()`.
1110 const Date& lastDate() const;
1111
1112 /// Return the number of days in the valid range of this calendar,
1113 /// which is defined to be 0 if this calendar is empty, and
1114 /// `lastDate() - firstDate() + 1` otherwise.
1115 int length() const;
1116
1117 /// Return the number of days in the valid range of this calendar that
1118 /// are considered business days -- i.e., are neither holidays nor
1119 /// weekend days.
1120 ///
1121 /// \note Note that `numBusinessDays() == length() - numNonBusinessDays()`.
1122 int numBusinessDays() const;
1123
1124 /// Return the number of days in the specified range
1125 /// `[beginDate .. endDate]` of this calendar that are considered
1126 /// business days -- i.e., are neither holidays nor weekend days.
1127 ///
1128 /// \pre The behavior is undefined unless `beginDate` and `endDate` are within
1129 /// the valid range of this calendar, and `beginDate <= endDate`.
1130 int numBusinessDays(const Date& beginDate, const Date& endDate) const;
1131
1132 /// Return the number of (unique) holiday codes associated with the
1133 /// specified `date` in this calendar if `date` is a holiday in this calendar, and 0 otherwise.
1134 ///
1135 /// \pre The behavior is undefined unless `date`
1136 /// is within the valid range of this calendar.
1137 int numHolidayCodes(const Date& date) const;
1138
1139 /// Return the total number of holiday codes for all holidays in this calendar.
1140 ///
1141 /// \note Note that this function is used primarily in conjunction
1142 /// with `reserveHolidayCodeCapacity`.
1143 int numHolidayCodesTotal() const;
1144
1145 /// Return the number of days in the valid range of this calendar that
1146 /// are individually marked as holidays, irrespective of whether or not
1147 /// the date is also considered a weekend day.
1148 int numHolidays() const;
1149
1150 /// Return the number of days in the valid range of this calendar that
1151 /// are *not* considered business days -- i.e., are either holidays,
1152 /// weekend days, or both.
1153 ///
1154 /// \note Note that `numNonBusinessDays() == length() - numBusinessDays()`.
1155 int numNonBusinessDays() const;
1156
1157 /// Return the number of days in the valid range of this calendar that
1158 /// are considered weekend days, irrespective of any designated
1159 /// holidays.
1160 int numWeekendDaysInRange() const;
1161
1162 /// Return the number of weekend-days transitions maintained by this
1163 /// calendar.
1164 int numWeekendDaysTransitions() const;
1165
1166 /// Return a reference providing non-modifiable access to the underlying
1167 /// `PackedCalendar`, which represents the same (mathematical) value as
1168 /// this calendar.
1169 const PackedCalendar& packedCalendar() const;
1170
1171 /// Return an iterator providing non-modifiable access to the last
1172 /// business day in this calendar. If this calendar has no valid
1173 /// business days, the returned iterator has the same value as that
1174 /// returned by `rendBusinessDays()`.
1176
1177 /// Return an iterator providing non-modifiable access to the first
1178 /// business day that occurs on or before the specified `date` in this
1179 /// calendar. If this calendar has no such business day, the returned
1180 /// iterator has the same value as that returned by `rendBusinessDays(date)`.
1181 ///
1182 /// \pre The behavior is undefined unless `date`
1183 /// is within the valid range of this calendar.
1185
1186 /// Return an iterator providing non-modifiable access to the last
1187 /// holiday code associated with the specified `date` in this calendar.
1188 /// If there are no holiday codes associated with `date`, the returned
1189 /// iterator has the same value as that returned by `rendHolidayCodes(date)`.
1190 ///
1191 /// \pre The behavior is undefined unless `date`
1192 /// is marked as a holiday in this calendar.
1194
1195 /// Return an iterator providing non-modifiable access to the last
1196 /// holiday code associated with the holiday referenced by the specified
1197 /// `iter`. If there are no holiday codes associated with the date
1198 /// referenced by `iter`, the returned iterator has the same value as
1199 /// that returned by `rendHolidayCodes(iter)`.
1200 ///
1201 /// \pre The behavior is undefined unless `iter` refers to a valid holiday of this calendar.
1203 rbeginHolidayCodes(const HolidayConstIterator& iter) const;
1204
1205 /// Return an iterator providing non-modifiable access to the last
1206 /// holiday in this calendar. If this calendar has no holidays, the
1207 /// returned iterator has the same value as that returned by
1208 /// `rendHolidays()`.
1210
1211 /// Return an iterator providing non-modifiable access to the first
1212 /// holiday that occurs on or before the specified `date` in this
1213 /// calendar. If this calendar has no such holiday, the returned
1214 /// iterator has the same value as that returned by `rendHolidays(date)`.
1215 ///
1216 /// \pre The behavior is undefined unless `date` is
1217 /// within the valid range of this calendar.
1219
1220 /// Return an iterator providing non-modifiable access to the last
1221 /// weekend-days transition in the chronological sequence of
1222 /// weekend-days transitions maintained by this calendar. If this
1223 /// calendar has no weekend-days transitions, the returned iterator has
1224 /// the same value as that returned by `rendWeekendDaysTransitions()`.
1227
1228 /// Return an iterator providing non-modifiable access to the element
1229 /// one before the first business day in this calendar.
1231
1232 /// Return an iterator providing non-modifiable access to the first
1233 /// business day that occurs before the specified `date` in this
1234 /// calendar. If this calendar has no such business day, the returned
1235 /// iterator has the same value as that returned by `rendBusinessDays()`.
1236 ///
1237 /// \pre The behavior is undefined unless `date` is
1238 /// within the valid range of this calendar.
1240
1241 /// Return an iterator providing non-modifiable access to the element
1242 /// one before the first holiday code associated with the specified `date`.
1243 ///
1244 /// \pre The behavior is undefined unless `date` is marked as a
1245 /// holiday in this calendar.
1247
1248 /// Return an iterator providing non-modifiable access to the element
1249 /// one before the first holiday code associated with the holiday
1250 /// referenced by the specified `iter`.
1251 ///
1252 /// \pre The behavior is undefined unless `iter` references a valid holiday in this calendar.
1254 rendHolidayCodes(const HolidayConstIterator& iter) const;
1255
1256 /// Return an iterator providing non-modifiable access to the element
1257 /// one before the first holiday in this calendar.
1259
1260 /// Return an iterator providing non-modifiable access to the first
1261 /// holiday that occurs before the specified `date` in this calendar.
1262 /// If this calendar has no such holiday, the returned iterator has the
1263 /// same value as that returned by `rendHolidays()`.
1264 ///
1265 /// \pre The behavior is undefined unless `date` is within the valid range of this calendar.
1267
1268 /// Return an iterator providing non-modifiable access to the element
1269 /// one before the first weekend-days transition in the chronological
1270 /// sequence of weekend-days transitions maintained by this calendar.
1273
1274 /// Return the weekend-days transition at the specified `index` in this
1275 /// calendar. For all `index` values from 0 to
1276 /// `numWeekendDaysTransitions() - 1` (inclusive), a unique weekend-days
1277 /// transition is returned. The mapping of `index` to weekend-days
1278 /// transition is invalidated when the set of weekend-days transitions
1279 /// is modified by an invocation of `addWeekendDay`, `addWeekendDays`,
1280 /// `addWeekendDaysTransition`, `intersectBusinessDays`,
1281 /// `intersectNonBusinessDays`, `removeAll`, `unionBusinessDays`, or `unionNonBusinessDays`.
1282 ///
1283 /// \pre The behavior is undefined unless
1284 /// `0 <= index < numWeekendDaysTransitions()`.
1286
1287 // Aspects
1288
1289 /// Return the allocator used by this object to supply memory.
1290 bslma::Allocator *allocator() const;
1291
1292 /// Write this value to the specified output `stream` using the
1293 /// specified `version` format and return a reference to the modifiable
1294 /// `stream`. If `version` is not supported, `stream` is unmodified.
1295 ///
1296 /// \note Note that `version` is not written to `stream`. See the `bslx`
1297 /// package-level documentation for more information on BDEX streaming
1298 /// of value-semantic types and containers.
1299 template <class STREAM>
1300 STREAM& bdexStreamOut(STREAM& stream, int version) const;
1301
1302 /// Format this object to the specified output `stream` at the (absolute
1303 /// value of) the optionally specified indentation `level` and return a
1304 /// reference to the modifiable `stream`. If `level` is specified,
1305 /// optionally specify `spacesPerLevel`, the number of spaces per
1306 /// indentation level for this and all of its nested objects. If
1307 /// `level` is negative, suppress indentation of the first line. If
1308 /// `spacesPerLevel` is negative, format the entire output on one line,
1309 /// suppressing all but the initial indentation (as governed by
1310 /// `level`). If `stream` is not valid on entry, this operation has no
1311 /// effect.
1312 bsl::ostream& print(bsl::ostream& stream,
1313 int level = 0,
1314 int spacesPerLevel = 4) const;
1315
1316#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE2.22
1317
1318 // DEPRECATED METHODS
1319
1320 /// Return the most current BDEX streaming version number supported by
1321 /// this class.
1322 ///
1323 /// @deprecated Use @ref maxSupportedBdexVersion(int) instead.
1324 static int maxSupportedBdexVersion();
1325
1326#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE2.22
1327
1328#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE3.0
1329
1330 /// Return the date of the first business day following the specified
1331 /// `initialDate`. For dates outside of the range of this calendar,
1332 /// only weekend days are considered non-business days.
1333 ///
1334 /// \pre The behavior is undefined if every day of the week is a weekend day, or if the
1335 /// resulting date would otherwise exceed the value
1336 /// `Date(9999, 12, 31)`.
1337 Date getNextBusinessDay(const Date& initialDate) const;
1338
1339 /// Return the date of the specified `nth` business day following the
1340 /// specified `initialDate`. For dates outside of the range of this
1341 /// calendar, only weekend days are considered non-business days.
1342 ///
1343 /// \pre The behavior is undefined unless `initialDate` is within the valid
1344 /// range and `1 <= nth` (or if every day of the week is a weekend day,
1345 /// or if the resulting date would otherwise exceed the value
1346 /// `Date(9999, 12, 31)`).
1347 Date getNextBusinessDay(const Date& initialDate, int nth) const;
1348
1349#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE3.0
1350
1351};
1352
1353// FREE OPERATORS
1354
1355/// Return `true` if the specified `lhs` and `rhs` calendars have the same
1356/// value, and `false` otherwise. Two calendars have the same value if they
1357/// have the same valid range (or are both empty), the same weekend days,
1358/// the same holidays, and each corresponding pair of holidays has the same
1359/// (ordered) set of associated holiday codes.
1360bool operator==(const Calendar& lhs, const Calendar& rhs);
1361
1362/// Return `true` if the specified `lhs` and `rhs` calendars do not have the
1363/// same value, and `false` otherwise. Two calendars do not have the same
1364/// value if they do not have the same valid range (and are not both empty),
1365/// do not have the same weekend days, do not have the same holidays, or,
1366/// for at least one corresponding pair of holidays, do not have the same
1367/// (ordered) set of associated holiday codes.
1368bool operator!=(const Calendar& lhs, const Calendar& rhs);
1369
1370/// Write the value of the specified `calendar` to the specified output
1371/// `stream`, and return a reference to the modifiable `stream`.
1372bsl::ostream& operator<<(bsl::ostream& stream, const Calendar& calendar);
1373
1374// FREE FUNCTIONS
1375
1376/// Pass the specified `object` to the specified `hashAlg`. This function
1377/// integrates with the `bslh` modular hashing system and effectively
1378/// provides a `bsl::hash` specialization for `Calendar`.
1379template <class HASHALG>
1380void hashAppend(HASHALG& hashAlg, const Calendar& object);
1381
1382/// Exchange the values of the specified `a` and `b` objects. This function
1383/// provides the no-throw exception-safety guarantee if the two objects were
1384/// created with the same allocator and the basic guarantee otherwise.
1385void swap(Calendar& a, Calendar& b);
1386
1387 // ===================================
1388 // class Calendar_BusinessDayConstIter
1389 // ===================================
1390
1391/// Provide read-only, sequential access in increasing (chronological) order
1392/// to the business days in a `Calendar` object.
1393///
1394/// See @ref bdlt_calendar
1396
1397 // DATA
1398 const bdlc::BitArray *d_nonBusinessDays_p; // pointer to the non-business
1399 // day bit array in the
1400 // calendar
1401
1402 Date d_firstDate; // first valid date of the
1403 // calendar
1404
1405 int d_currentOffset; // offset of the date to which
1406 // this iterator is pointing
1407 // (-1 indicates an 'end'
1408 // iterator)
1409
1410 // FRIENDS
1411 friend class Calendar;
1416
1417 private:
1418 // PRIVATE CREATORS
1419
1420 /// Create a business day iterator for a calendar defined by the
1421 /// specified `nonBusinessDays` and `firstDateOfCalendar`. If the
1422 /// specified `endIterFlag` is `false`, then this iterator references
1423 /// the first business day on or after the specified `startDate`;
1424 /// otherwise, this iterator references one business day *past* the
1425 /// first business day on or after `startDate`. If no business day
1426 /// matching the above specification exists, then this iterator
1427 /// references one day past the end of its range.
1428 ///
1429 /// \pre The behavior is undefined unless `startDate` is within the valid range of the
1430 /// calendar defined by `nonBusinessDays` and `firstDateOfCalendar`.
1431 Calendar_BusinessDayConstIter(const bdlc::BitArray& nonBusinessDays,
1432 const Date& firstDateOfCalendar,
1433 const Date& startDate,
1434 bool endIterFlag);
1435
1436 public:
1437 // PUBLIC TYPES
1439 typedef int difference_type;
1441
1442 /// The star operator returns a `PackedCalendar_DateRef` *by* *value*.
1444
1445 typedef bsl::bidirectional_iterator_tag iterator_category;
1446
1447 // CREATORS
1448
1449 /// Create an iterator having the value of the specified `original`
1450 /// iterator.
1452 const Calendar_BusinessDayConstIter& original);
1453
1454 /// Destroy this object.
1456
1457 // MANIPULATORS
1458
1459 /// Assign to this iterator the value of the specified `rhs` iterator,
1460 /// and return a reference providing modifiable access to this object.
1463
1464 /// Advance this iterator to refer to the next business day in the
1465 /// associated calendar, and return a reference providing modifiable access to this object.
1466 ///
1467 /// \pre The behavior is undefined unless, on entry,
1468 /// this iterator references a valid business day.
1470
1471 /// Regress this iterator to refer to the previous business day in the
1472 /// associated calendar, and return a reference providing modifiable access to this object.
1473 ///
1474 /// \pre The behavior is undefined unless, on entry,
1475 /// this iterator references a valid business day that is not the first
1476 /// business day for the associated calendar.
1478
1479 // ACCESSORS
1480
1481 /// Return a `PackedCalendar_DateRef` object that contains the date
1482 /// value of the business day referenced by this iterator.
1484
1485 /// Return a date proxy for the business day referenced by this
1486 /// iterator.
1488};
1489
1490// FREE OPERATORS
1491
1492/// Return `true` if the specified `lhs` and `rhs` iterators refer to the
1493/// same element in the same calendar, and `false` otherwise.
1494///
1495/// \pre The behavior is undefined unless `lhs` and `rhs` both iterate over the same calendar.
1496bool operator==(const Calendar_BusinessDayConstIter& lhs,
1498
1499/// Return `true` if the specified `lhs` and `rhs` iterators do not refer to
1500/// the same element in the same calendar, and `false` otherwise.
1501///
1502/// \pre The behavior is undefined unless `lhs` and `rhs` both iterate over the same
1503/// calendar.
1504bool operator!=(const Calendar_BusinessDayConstIter& lhs,
1506
1507/// Advance the specified `iterator` to refer to the next business day in
1508/// the associated calendar, and return the previous value of `iterator`.
1509///
1510/// \pre The behavior is undefined unless, on entry, `iterator` references a
1511/// valid business day.
1513 Calendar_BusinessDayConstIter& iterator, int);
1514
1515/// Regress the specified `iterator` to refer to the previous business day
1516/// in the associated calendar, and return the previous value of `iterator`.
1517///
1518/// \pre The behavior is undefined unless, on entry, `iterator` references a
1519/// valid business day that is not the first business day for the associated
1520/// calendar.
1522 Calendar_BusinessDayConstIter& iterator, int);
1523
1524// ============================================================================
1525// INLINE DEFINITIONS
1526// ============================================================================
1527
1528 // --------------
1529 // class Calendar
1530 // --------------
1531
1532// CLASS METHODS
1533
1534 // Aspects
1535
1536inline
1538{
1539 return PackedCalendar::maxSupportedBdexVersion(versionSelector);
1540}
1541
1542// MANIPULATORS
1543inline
1545{
1546 Calendar(rhs, d_packedCalendar.allocator()).swap(*this);
1547 return *this;
1548}
1549
1550inline
1552{
1553 Calendar(rhs, d_packedCalendar.allocator()).swap(*this);
1554 return *this;
1555}
1556
1557inline
1558int Calendar::addHolidayCodeIfInRange(const Date& date, int holidayCode)
1559{
1560 if (isInRange(date)) {
1562 return 0; // RETURN
1563 }
1564 return -1;
1565}
1566
1567inline
1569{
1570 if (isInRange(date)) {
1571 addHoliday(date);
1572 return 0; // RETURN
1573 }
1574 return -1;
1575}
1576
1577inline
1579 const DayOfWeekSet& weekendDays)
1580{
1581 d_packedCalendar.addWeekendDaysTransition(startDate, weekendDays);
1582 synchronizeCache();
1583}
1584
1585inline
1587{
1588 d_packedCalendar.intersectBusinessDays(other);
1589 synchronizeCache();
1590}
1591
1592inline
1594{
1595 intersectBusinessDays(other.d_packedCalendar);
1596}
1597
1598inline
1600{
1601 d_packedCalendar.intersectNonBusinessDays(other);
1602 synchronizeCache();
1603}
1604
1605inline
1607{
1608 intersectNonBusinessDays(other.d_packedCalendar);
1609}
1610
1611inline
1613{
1614 d_packedCalendar.removeAll();
1615 d_nonBusinessDays.removeAll();
1616}
1617
1618inline
1620{
1621 d_packedCalendar.removeHoliday(date);
1622
1623 if (true == isInRange(date) && false == isWeekendDay(date)) {
1624 d_nonBusinessDays.assign0(date - firstDate());
1625 }
1626}
1627
1628inline
1629void Calendar::removeHolidayCode(const Date& date, int holidayCode)
1630{
1631 d_packedCalendar.removeHolidayCode(date, holidayCode);
1632}
1633
1634inline
1636{
1637 d_packedCalendar.reserveHolidayCapacity(numHolidays);
1638}
1639
1640inline
1642{
1644}
1645
1646inline
1647void Calendar::setValidRange(const Date& firstDate, const Date& lastDate)
1648{
1652
1653 if (firstDate <= lastDate) {
1654 // For backwards compatibility, 'firstDate > lastDate' results in an
1655 // empty calendar (when asserts are not enabled).
1656
1657 d_nonBusinessDays.reserveCapacity(lastDate - firstDate + 1);
1658 }
1659
1660 d_packedCalendar.setValidRange(firstDate, lastDate);
1661
1662 synchronizeCache();
1663}
1664
1665inline
1667{
1668 unionBusinessDays(other.d_packedCalendar);
1669}
1670
1671inline
1673{
1674 unionNonBusinessDays(other.d_packedCalendar);
1675}
1676
1677 // Aspects
1678
1679template <class STREAM>
1680STREAM& Calendar::bdexStreamIn(STREAM& stream, int version)
1681{
1682 if (stream) {
1683 PackedCalendar inCal(allocator());
1684 inCal.bdexStreamIn(stream, version);
1685 if (!stream) {
1686 return stream; // RETURN
1687 }
1688 d_nonBusinessDays.reserveCapacity(inCal.length());
1689 d_packedCalendar.swap(inCal);
1690 synchronizeCache();
1691 }
1692 return stream;
1693}
1694
1695inline
1697{
1698 // 'swap' is undefined for objects with non-equal allocators.
1700 BSLS_ASSERT(d_packedCalendar.allocator() ==
1701 other.d_packedCalendar.allocator());
1703 bslalg::SwapUtil::swap(&d_packedCalendar, &other.d_packedCalendar);
1704 bslalg::SwapUtil::swap(&d_nonBusinessDays, &other.d_nonBusinessDays);
1705}
1706
1707// ACCESSORS
1708inline
1710{
1711 if (length()) {
1712 return Calendar_BusinessDayConstIter(d_nonBusinessDays,
1713 firstDate(),
1714 firstDate(),
1715 false); // RETURN
1716 }
1717
1718 return endBusinessDays();
1719}
1720
1721inline
1724{
1728
1729 return Calendar_BusinessDayConstIter(d_nonBusinessDays,
1730 firstDate(),
1731 date,
1732 false);
1733}
1734
1735inline
1738{
1739 return d_packedCalendar.beginHolidayCodes(date);
1740}
1741
1742inline
1745{
1746 return d_packedCalendar.beginHolidayCodes(iter);
1747}
1748
1749inline
1751{
1752 return d_packedCalendar.beginHolidays();
1753}
1754
1755inline
1757{
1758 return d_packedCalendar.beginHolidays(date);
1759}
1760
1761inline
1764{
1765 return d_packedCalendar.beginWeekendDaysTransitions();
1766}
1767
1768inline
1770{
1771 if (length()) {
1772 return BusinessDayConstIterator(d_nonBusinessDays,
1773 firstDate(),
1774 lastDate(),
1775 true); // RETURN
1776 }
1777 return BusinessDayConstIterator(d_nonBusinessDays,
1778 Date() + 1,
1779 Date(),
1780 true);
1781}
1782
1783inline
1786{
1790
1791 return BusinessDayConstIterator(d_nonBusinessDays,
1792 firstDate(),
1793 date,
1794 true);
1795}
1796
1797inline
1800{
1801 return d_packedCalendar.endHolidayCodes(date);
1802}
1803
1804inline
1807{
1808 return d_packedCalendar.endHolidayCodes(iter);
1809}
1810
1811inline
1813{
1814 return d_packedCalendar.endHolidays();
1815}
1816
1817inline
1819{
1820 return d_packedCalendar.endHolidays(date);
1821}
1822
1823inline
1826{
1827 return d_packedCalendar.endWeekendDaysTransitions();
1828}
1829
1830inline
1832{
1833 return d_packedCalendar.firstDate();
1834}
1835
1836inline
1837int Calendar::getNextBusinessDay(Date *nextBusinessDay, const Date& date) const
1838{
1840 BSLS_ASSERT_SAFE(nextBusinessDay);
1841 BSLS_ASSERT_SAFE(Date(9999, 12, 31) > date);
1842 BSLS_ASSERT_SAFE(isInRange(date + 1));
1844
1845 enum { e_SUCCESS = 0, e_FAILURE = 1 };
1846
1847 int offset = static_cast<int>(
1848 d_nonBusinessDays.find0AtMinIndex(date + 1 - firstDate()));
1849 if (0 <= offset) {
1850 *nextBusinessDay = firstDate() + offset;
1851 return e_SUCCESS; // RETURN
1852 }
1853
1854 return e_FAILURE;
1855}
1856
1857
1858inline
1859Date Calendar::holiday(int index) const
1860{
1861 return d_packedCalendar.holiday(index);
1862}
1863
1864inline
1865int Calendar::holidayCode(const Date& date, int index) const
1866{
1867 return d_packedCalendar.holidayCode(date, index);
1868}
1869
1870inline
1871bool Calendar::isBusinessDay(const Date& date) const
1872{
1873 return !isNonBusinessDay(date);
1874}
1875
1876inline
1877bool Calendar::isHoliday(const Date& date) const
1878{
1879 return d_packedCalendar.isHoliday(date);
1880}
1881
1882inline
1883bool Calendar::isInRange(const Date& date) const
1884{
1885 return d_packedCalendar.isInRange(date);
1886}
1887
1888inline
1889bool Calendar::isNonBusinessDay(const Date& date) const
1890{
1894
1895 return d_nonBusinessDays[date - firstDate()];
1896}
1897
1898inline
1899bool Calendar::isWeekendDay(const Date& date) const
1900{
1901 return d_packedCalendar.isWeekendDay(date);
1902}
1903
1904inline
1906{
1907 return d_packedCalendar.isWeekendDay(dayOfWeek);
1908}
1909
1910inline
1912{
1913 return d_packedCalendar.lastDate();
1914}
1915
1916inline
1918{
1919 return static_cast<int>(d_nonBusinessDays.length());
1920}
1921
1922inline
1924{
1925 return static_cast<int>(d_nonBusinessDays.num0());
1926}
1927
1928inline
1929int Calendar::numBusinessDays(const Date& beginDate, const Date& endDate) const
1930{
1932 BSLS_ASSERT_SAFE(isInRange(beginDate));
1933 BSLS_ASSERT_SAFE(isInRange(endDate));
1934 BSLS_ASSERT_SAFE(beginDate <= endDate);
1936
1937 return static_cast<int>(d_nonBusinessDays.num0(beginDate - firstDate(),
1938 endDate - firstDate() + 1));
1939}
1940
1941inline
1942int Calendar::numHolidayCodes(const Date& date) const
1943{
1944 return d_packedCalendar.numHolidayCodes(date);
1945}
1946
1947inline
1949{
1950 return d_packedCalendar.numHolidayCodesTotal();
1951}
1952
1953inline
1955{
1956 return d_packedCalendar.numHolidays();
1957}
1958
1959inline
1961{
1962 return static_cast<int>(d_nonBusinessDays.num1());
1963}
1964
1965inline
1967{
1968 return d_packedCalendar.numWeekendDaysInRange();
1969}
1970
1971inline
1973{
1974 return d_packedCalendar.numWeekendDaysTransitions();
1975}
1976
1977inline
1979{
1980 return d_packedCalendar;
1981}
1982
1983inline
1988
1989inline
1992{
1994
1996}
1997
1998inline
2001{
2002 return d_packedCalendar.rbeginHolidayCodes(date);
2003}
2004
2005inline
2008{
2009 return d_packedCalendar.rbeginHolidayCodes(iter);
2010}
2011
2012inline
2014{
2015 return d_packedCalendar.rbeginHolidays();
2016}
2017
2018inline
2021{
2022 return d_packedCalendar.rbeginHolidays(date);
2023}
2024
2025inline
2028{
2029 return d_packedCalendar.rbeginWeekendDaysTransitions();
2030}
2031
2032inline
2037
2038inline
2041{
2043
2045}
2046
2047inline
2050{
2051 return d_packedCalendar.rendHolidayCodes(date);
2052}
2053
2054inline
2057{
2058 return d_packedCalendar.rendHolidayCodes(iter);
2059}
2060
2061inline
2063{
2064 return d_packedCalendar.rendHolidays();
2065}
2066
2067inline
2069 Calendar::rendHolidays(const Date& date) const
2070{
2071 return d_packedCalendar.rendHolidays(date);
2072}
2073
2074inline
2077{
2078 return d_packedCalendar.rendWeekendDaysTransitions();
2079}
2080
2081inline
2084{
2085 return d_packedCalendar.weekendDaysTransition(index);
2086}
2087
2088 // Aspects
2089
2090inline
2092{
2093 return d_packedCalendar.allocator();
2094}
2095
2096template <class STREAM>
2097inline
2098STREAM& Calendar::bdexStreamOut(STREAM& stream, int version) const
2099{
2100
2101 d_packedCalendar.bdexStreamOut(stream, version);
2102 return stream;
2103}
2104
2105inline
2106bsl::ostream& Calendar::print(bsl::ostream& stream,
2107 int level,
2108 int spacesPerLevel) const
2109{
2110 return d_packedCalendar.print(stream, level, spacesPerLevel);
2111}
2112
2113#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE2.22
2114
2115// DEPRECATED METHODS
2116inline
2118{
2119 return 1;
2120}
2121
2122#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE2.22
2123
2124} // close package namespace
2125
2126// FREE OPERATORS
2127inline
2128bool bdlt::operator==(const Calendar& lhs, const Calendar& rhs)
2129{
2130 return lhs.d_packedCalendar == rhs.d_packedCalendar;
2131}
2132
2133inline
2134bool bdlt::operator!=(const Calendar& lhs, const Calendar& rhs)
2135{
2136 return lhs.d_packedCalendar != rhs.d_packedCalendar;
2137}
2138
2139inline
2140bsl::ostream& bdlt::operator<<(bsl::ostream& stream, const Calendar& calendar)
2141{
2142 calendar.print(stream, 0, -1);
2143 return stream;
2144}
2145
2146// FREE FUNCTIONS
2147template <class HASHALG>
2148inline
2149void bdlt::hashAppend(HASHALG& hashAlg, const Calendar& object)
2150{
2151 using ::BloombergLP::bslh::hashAppend;
2152 hashAppend(hashAlg, object.d_packedCalendar);
2153}
2154
2155namespace bdlt {
2156
2157 // -----------------------------------
2158 // class Calendar_BusinessDayConstIter
2159 // -----------------------------------
2160
2161// CREATORS
2162inline
2163Calendar_BusinessDayConstIter::Calendar_BusinessDayConstIter(
2164 const Calendar_BusinessDayConstIter& original)
2165: d_nonBusinessDays_p(original.d_nonBusinessDays_p)
2166, d_firstDate(original.d_firstDate)
2167, d_currentOffset(original.d_currentOffset)
2168{
2169}
2170
2171inline
2175
2176// MANIPULATORS
2177inline
2180{
2181 d_nonBusinessDays_p = rhs.d_nonBusinessDays_p;
2182 d_firstDate = rhs.d_firstDate;
2183 d_currentOffset = rhs.d_currentOffset;
2184 return *this;
2185}
2186
2187inline
2189{
2190 BSLS_ASSERT_SAFE(d_currentOffset >= 0);
2191
2192 d_currentOffset = static_cast<int>(
2193 d_nonBusinessDays_p->find0AtMinIndex(d_currentOffset + 1));
2194 return *this;
2195}
2196
2197inline
2199{
2200 if (-1 == d_currentOffset) {
2201 d_currentOffset = static_cast<int>(d_nonBusinessDays_p->
2202 find0AtMaxIndex(0, d_nonBusinessDays_p->length()));
2203 }
2204 else {
2205 d_currentOffset = static_cast<int>(d_nonBusinessDays_p->
2206 find0AtMaxIndex(0, d_currentOffset));
2207 }
2208
2209 BSLS_ASSERT_SAFE(0 <= d_currentOffset);
2210
2211 return *this;
2212}
2213
2214inline
2216 Calendar_BusinessDayConstIter& iterator, int)
2217{
2218 Calendar_BusinessDayConstIter tmp(iterator);
2219 ++iterator;
2220 return tmp;
2221}
2222
2223inline
2225 Calendar_BusinessDayConstIter& iterator, int)
2226{
2227 Calendar_BusinessDayConstIter tmp(iterator);
2228 --iterator;
2229 return tmp;
2230}
2231
2232// ACCESSORS
2233inline
2235{
2236 return PackedCalendar_DateRef(d_firstDate + d_currentOffset);
2237}
2238
2239inline
2244
2245} // close package namespace
2246
2247// FREE OPERATORS
2248inline
2249bool bdlt::operator==(const Calendar_BusinessDayConstIter& lhs,
2250 const Calendar_BusinessDayConstIter& rhs)
2251{
2252 BSLS_ASSERT_SAFE(lhs.d_nonBusinessDays_p == rhs.d_nonBusinessDays_p);
2253
2254 return lhs.d_firstDate == rhs.d_firstDate
2255 && lhs.d_currentOffset == rhs.d_currentOffset;
2256}
2257
2258inline
2259bool bdlt::operator!=(const Calendar_BusinessDayConstIter& lhs,
2260 const Calendar_BusinessDayConstIter& rhs)
2261{
2262 BSLS_ASSERT_SAFE(lhs.d_nonBusinessDays_p == rhs.d_nonBusinessDays_p);
2263
2264 return lhs.d_firstDate != rhs.d_firstDate
2265 || lhs.d_currentOffset != rhs.d_currentOffset;
2266}
2267
2268
2269
2270// TRAITS
2271
2272namespace bslma {
2273
2274template <>
2276
2277} // close namespace bslma
2278
2279
2280#endif
2281
2282// ----------------------------------------------------------------------------
2283// Copyright 2018 Bloomberg Finance L.P.
2284//
2285// Licensed under the Apache License, Version 2.0 (the "License");
2286// you may not use this file except in compliance with the License.
2287// You may obtain a copy of the License at
2288//
2289// http://www.apache.org/licenses/LICENSE-2.0
2290//
2291// Unless required by applicable law or agreed to in writing, software
2292// distributed under the License is distributed on an "AS IS" BASIS,
2293// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2294// See the License for the specific language governing permissions and
2295// limitations under the License.
2296// ----------------------------- END-OF-FILE ----------------------------------
2297
2298/** @} */
2299/** @} */
2300/** @} */
Definition bdlc_bitarray.h:525
bsl::size_t num0(bsl::size_t begin=0, bsl::size_t end=k_INVALID_INDEX) const
Definition bdlc_bitarray.h:1892
bsl::size_t length() const
Return the number of bits in this array.
Definition bdlc_bitarray.h:1886
bsl::size_t num1(bsl::size_t begin=0, bsl::size_t end=k_INVALID_INDEX) const
Definition bdlc_bitarray.h:1904
void removeAll()
Definition bdlc_bitarray.h:1649
bsl::size_t find0AtMinIndex(bsl::size_t begin=0, bsl::size_t end=k_INVALID_INDEX) const
Definition bdlc_bitarray.h:1832
void assign0(bsl::size_t index)
Definition bdlc_bitarray.h:1484
void reserveCapacity(bsl::size_t numBits)
Definition bdlc_bitarray.h:1657
Definition bdlt_calendarreverseiteratoradapter.h:298
Definition bdlt_calendar.h:1395
friend bool operator==(const Calendar_BusinessDayConstIter &, const Calendar_BusinessDayConstIter &)
Date value_type
Definition bdlt_calendar.h:1438
int difference_type
Definition bdlt_calendar.h:1439
friend bool operator!=(const Calendar_BusinessDayConstIter &, const Calendar_BusinessDayConstIter &)
PackedCalendar_DateRef operator*() const
Definition bdlt_calendar.h:2234
PackedCalendar_DateProxy pointer
Definition bdlt_calendar.h:1440
PackedCalendar_DateRef reference
The star operator returns a PackedCalendar_DateRef by value.
Definition bdlt_calendar.h:1443
Calendar_BusinessDayConstIter & operator++()
Definition bdlt_calendar.h:2188
Calendar_BusinessDayConstIter & operator=(const Calendar_BusinessDayConstIter &rhs)
Definition bdlt_calendar.h:2178
PackedCalendar_DateProxy operator->() const
Definition bdlt_calendar.h:2240
bsl::bidirectional_iterator_tag iterator_category
Definition bdlt_calendar.h:1445
~Calendar_BusinessDayConstIter()
Destroy this object.
Definition bdlt_calendar.h:2172
Calendar_BusinessDayConstIter & operator--()
Definition bdlt_calendar.h:2198
Definition bdlt_calendar.h:570
int getNextBusinessDay(Date *nextBusinessDay, const Date &date, int nth) const
BusinessDayConstIterator endBusinessDays() const
Definition bdlt_calendar.h:1769
WeekendDaysTransitionConstIterator endWeekendDaysTransitions() const
Definition bdlt_calendar.h:1825
int numHolidayCodesTotal() const
Definition bdlt_calendar.h:1948
HolidayConstIterator beginHolidays() const
Definition bdlt_calendar.h:1750
PackedCalendar::WeekendDaysTransitionConstReverseIterator WeekendDaysTransitionConstReverseIterator
Definition bdlt_calendar.h:629
void removeHoliday(const Date &date)
Definition bdlt_calendar.h:1619
void unionBusinessDays(const Calendar &other)
Definition bdlt_calendar.h:1666
Calendar_BusinessDayConstIter BusinessDayConstIterator
Definition bdlt_calendar.h:608
int numNonBusinessDays() const
Definition bdlt_calendar.h:1960
static int maxSupportedBdexVersion()
Definition bdlt_calendar.h:2117
void unionNonBusinessDays(const Calendar &other)
Definition bdlt_calendar.h:1672
HolidayConstReverseIterator rendHolidays() const
Definition bdlt_calendar.h:2062
void addWeekendDay(DayOfWeek::Enum weekendDay)
Date getNextBusinessDay(const Date &initialDate) const
BusinessDayConstReverseIterator rendBusinessDays() const
Definition bdlt_calendar.h:2033
HolidayCodeConstReverseIterator rendHolidayCodes(const Date &date) const
Definition bdlt_calendar.h:2049
Date getNextBusinessDay(const Date &initialDate, int nth) const
PackedCalendar::WeekendDaysTransition WeekendDaysTransition
Definition bdlt_calendar.h:623
void setValidRange(const Date &firstDate, const Date &lastDate)
Definition bdlt_calendar.h:1647
PackedCalendar::HolidayCodeConstIterator HolidayCodeConstIterator
Definition bdlt_calendar.h:612
void removeHolidayCode(const Date &date, int holidayCode)
Definition bdlt_calendar.h:1629
bool isInRange(const Date &date) const
Definition bdlt_calendar.h:1883
HolidayCodeConstIterator beginHolidayCodes(const Date &date) const
Definition bdlt_calendar.h:1737
WeekendDaysTransitionConstReverseIterator rendWeekendDaysTransitions() const
Definition bdlt_calendar.h:2076
void addDay(const Date &date)
void addHoliday(const Date &date)
int holidayCode(const Date &date, int index) const
Definition bdlt_calendar.h:1865
HolidayCodeConstIterator endHolidayCodes(const Date &date) const
Definition bdlt_calendar.h:1799
void addWeekendDaysTransition(const Date &startDate, const DayOfWeekSet &weekendDays)
Definition bdlt_calendar.h:1578
PackedCalendar::HolidayConstIterator HolidayConstIterator
Definition bdlt_calendar.h:610
Calendar(bslma::Allocator *basicAllocator=0)
WeekendDaysTransition weekendDaysTransition(int index) const
Definition bdlt_calendar.h:2083
int getNextBusinessDay(Date *nextBusinessDay, const Date &date) const
Definition bdlt_calendar.h:1837
void unionNonBusinessDays(const PackedCalendar &other)
int numHolidayCodes(const Date &date) const
Definition bdlt_calendar.h:1942
bool isNonBusinessDay(const Date &date) const
Definition bdlt_calendar.h:1889
friend void hashAppend(HASHALG &hashAlg, const Calendar &)
HolidayConstReverseIterator rbeginHolidays() const
Definition bdlt_calendar.h:2013
WeekendDaysTransitionConstIterator beginWeekendDaysTransitions() const
Definition bdlt_calendar.h:1763
void addHolidayCode(const Date &date, int holidayCode)
BusinessDayConstReverseIterator rbeginBusinessDays() const
Definition bdlt_calendar.h:1984
void reserveHolidayCodeCapacity(int numHolidayCodes)
Definition bdlt_calendar.h:1641
const Date & firstDate() const
Definition bdlt_calendar.h:1831
bool isHoliday(const Date &date) const
Definition bdlt_calendar.h:1877
const Date & lastDate() const
Definition bdlt_calendar.h:1911
Calendar(const Calendar &original, bslma::Allocator *basicAllocator=0)
BusinessDayConstIterator beginBusinessDays() const
Definition bdlt_calendar.h:1709
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlt_calendar.h:2091
int numBusinessDays() const
Definition bdlt_calendar.h:1923
WeekendDaysTransitionConstReverseIterator rbeginWeekendDaysTransitions() const
Definition bdlt_calendar.h:2027
~Calendar()
Destroy this object.
int addHolidayCodeIfInRange(const Date &date, int holidayCode)
Definition bdlt_calendar.h:1558
STREAM & bdexStreamIn(STREAM &stream, int version)
Definition bdlt_calendar.h:1680
void intersectBusinessDays(const Calendar &other)
Definition bdlt_calendar.h:1593
void addWeekendDays(const DayOfWeekSet &weekendDays)
HolidayConstIterator endHolidays() const
Definition bdlt_calendar.h:1812
const PackedCalendar & packedCalendar() const
Definition bdlt_calendar.h:1978
Date holiday(int index) const
Definition bdlt_calendar.h:1859
void intersectNonBusinessDays(const Calendar &other)
Definition bdlt_calendar.h:1606
PackedCalendar::HolidayCodeConstReverseIterator HolidayCodeConstReverseIterator
Definition bdlt_calendar.h:621
void swap(Calendar &other)
Definition bdlt_calendar.h:1696
int length() const
Definition bdlt_calendar.h:1917
bool isWeekendDay(const Date &date) const
Definition bdlt_calendar.h:1899
void reserveHolidayCapacity(int numHolidays)
Definition bdlt_calendar.h:1635
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
Definition bdlt_calendar.h:2106
int numWeekendDaysTransitions() const
Definition bdlt_calendar.h:1972
STREAM & bdexStreamOut(STREAM &stream, int version) const
Definition bdlt_calendar.h:2098
PackedCalendar::WeekendDaysTransitionConstIterator WeekendDaysTransitionConstIterator
Definition bdlt_calendar.h:626
HolidayCodeConstReverseIterator rbeginHolidayCodes(const Date &date) const
Definition bdlt_calendar.h:2000
bool isBusinessDay(const Date &date) const
Definition bdlt_calendar.h:1871
Calendar(const bdlt::PackedCalendar &packedCalendar, bslma::Allocator *basicAllocator=0)
PackedCalendar::HolidayConstReverseIterator HolidayConstReverseIterator
Definition bdlt_calendar.h:618
friend bool operator==(const Calendar &, const Calendar &)
Calendar & operator=(const Calendar &rhs)
Definition bdlt_calendar.h:1544
int numWeekendDaysInRange() const
Definition bdlt_calendar.h:1966
int numHolidays() const
Definition bdlt_calendar.h:1954
void unionBusinessDays(const PackedCalendar &other)
int addHolidayIfInRange(const Date &date)
Definition bdlt_calendar.h:1568
CalendarReverseIteratorAdapter< BusinessDayConstIterator > BusinessDayConstReverseIterator
Definition bdlt_calendar.h:615
friend bool operator!=(const Calendar &, const Calendar &)
Calendar(const Date &firstDate, const Date &lastDate, bslma::Allocator *basicAllocator=0)
void removeAll()
Definition bdlt_calendar.h:1612
Definition bdlt_date.h:294
Definition bdlt_dayofweekset.h:402
Definition bdlt_packedcalendar.h:1491
Definition bdlt_packedcalendar.h:1529
Definition bdlt_packedcalendar.h:1689
Definition bdlt_packedcalendar.h:1565
Definition bdlt_packedcalendar.h:593
void reserveHolidayCodeCapacity(int numHolidayCodes)
Definition bdlt_packedcalendar.h:2419
HolidayConstReverseIterator rbeginHolidays() const
Definition bdlt_packedcalendar.h:3182
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
int numWeekendDaysInRange() const
void setValidRange(const Date &firstDate, const Date &lastDate)
const Date & firstDate() const
Definition bdlt_packedcalendar.h:3003
int numHolidays() const
Definition bdlt_packedcalendar.h:3135
int numHolidayCodesTotal() const
Definition bdlt_packedcalendar.h:3129
void removeHoliday(const Date &date)
WeekendDaysTransitionConstReverseIterator rendWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:3256
HolidayCodeConstReverseIterator rendHolidayCodes(const Date &date) const
Definition bdlt_packedcalendar.h:3222
int holidayCode(const Date &date, int index) const
Definition bdlt_packedcalendar.h:3038
WeekendDaysTransitionConstIterator endWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:2997
WeekendDaysTransitionSequence::const_iterator WeekendDaysTransitionConstIterator
Definition bdlt_packedcalendar.h:648
void removeHolidayCode(const Date &date, int holidayCode)
STREAM & bdexStreamIn(STREAM &stream, int version)
Definition bdlt_packedcalendar.h:2429
void addWeekendDaysTransition(const Date &startDate, const DayOfWeekSet &weekendDays)
void reserveHolidayCapacity(int numHolidays)
Definition bdlt_packedcalendar.h:2410
HolidayConstIterator beginHolidays() const
Definition bdlt_packedcalendar.h:2926
const Date & lastDate() const
Definition bdlt_packedcalendar.h:3109
WeekendDaysTransitionPrivate WeekendDaysTransition
Definition bdlt_packedcalendar.h:630
bool isHoliday(const Date &date) const
Definition bdlt_packedcalendar.h:3064
HolidayCodeConstReverseIterator rbeginHolidayCodes(const Date &date) const
Definition bdlt_packedcalendar.h:3164
void swap(PackedCalendar &other)
void intersectNonBusinessDays(const PackedCalendar &other)
WeekendDaysTransition weekendDaysTransition(int index) const
Definition bdlt_packedcalendar.h:3264
HolidayConstIterator endHolidays() const
Definition bdlt_packedcalendar.h:2977
bool isInRange(const Date &date) const
Definition bdlt_packedcalendar.h:3079
void intersectBusinessDays(const PackedCalendar &other)
bsl::reverse_iterator< WeekendDaysTransitionSequence::const_iterator > WeekendDaysTransitionConstReverseIterator
Definition bdlt_packedcalendar.h:652
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlt_packedcalendar.h:3275
int length() const
Definition bdlt_packedcalendar.h:3117
bdlt::Date holiday(int index) const
Definition bdlt_packedcalendar.h:3029
static int maxSupportedBdexVersion()
Definition bdlt_packedcalendar.h:3366
STREAM & bdexStreamOut(STREAM &stream, int version) const
Definition bdlt_packedcalendar.h:3281
int numWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:3141
WeekendDaysTransitionConstIterator beginWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:2946
HolidayConstReverseIterator rendHolidays() const
Definition bdlt_packedcalendar.h:3240
WeekendDaysTransitionConstReverseIterator rbeginWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:3198
bool isWeekendDay(const Date &date) const
int numHolidayCodes(const Date &date) const
static void swap(T *a, T *b)
Definition bslalg_swaputil.h:182
Definition bslma_allocator.h:545
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_PRECONDITIONS_END()
Definition bsls_preconditions.h:131
#define BSLS_PRECONDITIONS_BEGIN()
Definition bsls_preconditions.h:130
void hashAppend(HASH_ALGORITHM &hashAlgorithm, const BigEndianInt16 &object)
Definition bbldc_basicisma30360.h:112
Calendar_BusinessDayConstIter operator++(Calendar_BusinessDayConstIter &iterator, int)
Definition bdlt_calendar.h:2215
bool operator==(const Calendar &lhs, const Calendar &rhs)
bsl::ostream & operator<<(bsl::ostream &stream, const Calendar &calendar)
void hashAppend(HASHALG &hashAlg, const Calendar &object)
bool operator!=(const Calendar &lhs, const Calendar &rhs)
Calendar_BusinessDayConstIter operator--(Calendar_BusinessDayConstIter &iterator, int)
Definition bdlt_calendar.h:2224
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
Definition baljsn_encoder_testtypes.h:76
Enum
Enumerated day-of-week values.
Definition bdlt_dayofweek.h:125
Definition bslma_usesbslmaallocator.h:344