BDE 4.14.0 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
563/// maintained (internally) in order of increasing value. Note that the
564/// behavior of requesting *any* calendar information for a supplied date
565/// whose value is outside the current *valid* *range* for that calendar
566/// (unless otherwise noted, e.g., `isWeekendDay`) is undefined.
567///
568/// See @ref bdlt_calendar
569class Calendar {
570
571 // DATA
572 PackedCalendar d_packedCalendar;
573 // the packed calendar object, which contains
574 // the weekend day and holiday information
575
576 bdlc::BitArray d_nonBusinessDays;
577 // cache of non-business days; note that the end
578 // of the valid range is defined by
579 // 'd_packedCalendar.firstDate() + length() - 1'
580
581 // FRIENDS
582 friend bool operator==(const Calendar&, const Calendar&);
583 friend bool operator!=(const Calendar&, const Calendar&);
584 template <class HASHALG>
585 friend void hashAppend(HASHALG& hashAlg, const Calendar&);
586
587 private:
588 // PRIVATE MANIPULATORS
589
590 /// Synchronize this calendar's cache by first clearing the cache, then
591 /// repopulating it with the holiday and weekend information from this
592 /// calendar's `d_packedCalendar`. Note that this method is only
593 /// **exception-neutral**; exception safety and rollback must be
594 /// handled by the caller.
595 void synchronizeCache();
596
597 // PRIVATE ACCESSORS
598
599 /// Return `true` if this calendar's cache correctly represents the
600 /// holiday and weekend information stored in this calendar's
601 /// `d_packedCalendar`, and `false` otherwise.
602 bool isCacheSynchronized() const;
603
604 public:
605 // TYPES
607
609
611
614
617
620
622
625
628
629 // CLASS METHODS
630
631 // Aspects
632
633 /// Return the maximum valid BDEX format version, as indicated by the
634 /// specified `versionSelector`, to be passed to the `bdexStreamOut`
635 /// method. Note that it is highly recommended that `versionSelector`
636 /// be formatted as "YYYYMMDD", a date representation. Also note that
637 /// `versionSelector` should be a *compile*-time-chosen value that
638 /// selects a format version supported by both externalizer and
639 /// unexternalizer. See the `bslx` package-level documentation for more
640 /// information on BDEX streaming of value-semantic types and
641 /// containers.
642 static int maxSupportedBdexVersion(int versionSelector);
643
644 // CREATORS
645
646 /// Create an empty calendar, i.e., a calendar having an empty valid
647 /// range. Optionally specify a `basicAllocator` used to supply memory.
648 /// If `basicAllocator` is 0, the currently installed default allocator
649 /// is used.
650 explicit Calendar(bslma::Allocator *basicAllocator = 0);
651
652 /// Create a calendar having a valid range from the specified
653 /// `firstDate` through the specified `lastDate`. Optionally specify a
654 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
655 /// the currently installed default allocator is used. The behavior is
656 /// undefined unless `firstDate <= lastDate`.
658 const Date& lastDate,
659 bslma::Allocator *basicAllocator = 0);
660
661 /// Create a calendar having the same value as the specified
662 /// `packedCalendar`. Optionally specify a `basicAllocator` used to
663 /// supply memory. If `basicAllocator` is 0, the currently installed
664 /// default allocator is used.
666 bslma::Allocator *basicAllocator = 0);
667
668 /// Create a calendar having the value of the specified `original`
669 /// calendar. Optionally specify a `basicAllocator` used to supply
670 /// memory. If `basicAllocator` is 0, the currently installed default
671 /// allocator is used.
672 Calendar(const Calendar& original, bslma::Allocator *basicAllocator = 0);
673
674 /// Destroy this object.
676
677 // MANIPULATORS
678
679 /// Assign to this calendar the value of the specified `rhs` calendar,
680 /// and return a reference providing modifiable access to this calendar.
681 /// See {Iterator Invalidation} for information regarding which
682 /// iterators are affected by the use of these methods.
683 Calendar& operator=(const Calendar& rhs);
684 Calendar& operator=(const PackedCalendar& rhs);
685
686 /// Extend the valid range (if necessary) of this calendar to include
687 /// the specified `date` value.
688 void addDay(const Date& date);
689
690 /// Mark the specified `date` as a holiday (i.e., a non-business day)
691 /// in this calendar. Extend the valid range of this calendar if
692 /// necessary. If `date` is already marked as a holiday, this method
693 /// has no effect. See {Iterator Invalidation} for information
694 /// regarding which iterators are affected by the use of this method.
695 void addHoliday(const Date& date);
696
697 /// Mark the specified `date` as a holiday (i.e., a non-business day) in
698 /// this calendar and add the specified `holidayCode` (if not already
699 /// present) to the ordered set of codes associated with `date`.
700 /// Extend the valid range of this calendar if necessary. If
701 /// `holidayCode` is already a code for `date`, this method has no
702 /// effect. See {Iterator Invalidation} for information regarding
703 /// which iterators are affected by the use of this method. Note that
704 /// this method may be called repeatedly with the same value for `date`
705 /// to build up a set of holiday codes for that date.
706 void addHolidayCode(const Date& date, int holidayCode);
707
708 /// Mark the specified `date` as a holiday (i.e., a non-business day)
709 /// in this calendar and add the specified `holidayCode` (if not
710 /// already present) to the set of codes associated with `date`, if
711 /// `date` is within the valid range of this calendar. Return 0 if
712 /// `date` is in range, and a non-zero value otherwise. If
713 /// `holidayCode` is already a code for `date`, or if `date` is not in
714 /// the valid range, this method has no effect. See
715 /// {Iterator Invalidation} for information regarding which iterators
716 /// are affected by the use of this method. Note that this method may,
717 /// at the expense of verifying `isInRange(date)` for each invocation,
718 /// be called repeatedly with the same value for `date` to build up a
719 /// set of holiday codes for that date.
720 int addHolidayCodeIfInRange(const Date& date, int holidayCode);
721
722 /// Mark the specified `date` as a holiday (i.e., a non-business day) in
723 /// this calendar if `date` is within the valid range. Return 0 if
724 /// `date` is in range, and a non-zero value otherwise. This method has
725 /// no effect if `date` is already marked as a holiday or is not in the
726 /// valid range. See {Iterator Invalidation} for information regarding
727 /// which iterators are affected by the use of this method.
728 int addHolidayIfInRange(const Date& date);
729
730 /// Add the specified `weekendDay` to the set of weekend days associated
731 /// with the weekend-days transition at January 1, 0001 maintained by
732 /// this calendar. Create a transition at January 1, 0001 if one does
733 /// not exist. See {Iterator Invalidation} for information regarding
734 /// which iterators are affected by the use of this method. The
735 /// behavior is undefined unless no weekend-days transitions were added
736 /// to this calendar via the `addWeekendDaysTransition` method.
738
739 /// Add the specified `weekendDays` to the set of weekend days
740 /// associated with the weekend-days transition at January 1, 0001
741 /// maintained by this calendar. Create a transition at January 1, 0001
742 /// if one does not exist. See {Iterator Invalidation} for information
743 /// regarding which iterators are affected by the use of this method.
744 /// The behavior is undefined unless no weekend-days transitions were
745 /// added to this calendar via the `addWeekendDaysTransition` method.
746 void addWeekendDays(const DayOfWeekSet& weekendDays);
747
748 /// Add to this calendar a weekend-days transition on the specified
749 /// `startDate` having the specified `weekendDays` set. If a
750 /// weekend-days transition already exists on `startDate`, replace the
751 /// set of weekend days of that transition with `weekendDays`. See
752 /// {Iterator Invalidation} for information regarding which iterators
753 /// are affected by the use of this method. Note that this method does
754 /// not extend the valid range of the calendar.
755 void addWeekendDaysTransition(const Date& startDate,
756 const DayOfWeekSet& weekendDays);
757
758 void intersectBusinessDays(const Calendar& other);
759 /// Merge the specified `other` calendar into this calendar such that
760 /// the valid range of this calendar becomes the *intersection* of the
761 /// two calendars' ranges, and the weekend days and holidays for this
762 /// calendar become the union of those (non-business) days from the two
763 /// calendars -- i.e., the valid business days of this calendar become
764 /// the intersection of those of the two original calendar values over
765 /// the *intersection* of their ranges. For each holiday that remains,
766 /// the resulting holiday codes in this calendar will be the union of
767 /// the corresponding original holiday codes. See
768 /// {Iterator Invalidation} for information regarding which iterators
769 /// are affected by the use of this method.
770 void intersectBusinessDays(const PackedCalendar& other);
771
772 void intersectNonBusinessDays(const Calendar& other);
773 /// Merge the specified `other` calendar into this calendar such that
774 /// the valid range of this calendar becomes the *intersection* of the
775 /// two calendars' ranges, the weekend days for this calendar become the
776 /// intersection of those days from the two calendars, and the holidays
777 /// for this calendar become the set of days that are a holiday in one
778 /// of the calendars and a non-business day in the other calendar --
779 /// i.e., the valid business days of this calendar become the union of
780 /// those of the two original calendars over the *intersection* of their
781 /// ranges. For each holiday that remains, the resulting holiday codes
782 /// in this calendar will be the union of the corresponding original
783 /// holiday codes. See {Iterator Invalidation} for information
784 /// regarding which iterators are affected by the use of this method.
785 void intersectNonBusinessDays(const PackedCalendar& other);
786
787 /// Remove all information from this calendar, leaving it with its
788 /// default constructed "empty" value. See {Iterator Invalidation} for
789 /// information regarding which iterators are affected by the use of
790 /// this method.
791 void removeAll();
792
793 /// Remove from this calendar the holiday having the specified `date` if
794 /// such a holiday exists. This operation has no effect if `date` is
795 /// not a holiday in this calendar. See {Iterator Invalidation} for
796 /// information regarding which iterators are affected by the use of
797 /// this method. Note that this method is defined for all `date`
798 /// values, not just those that fall within the valid range, and may be
799 /// invoked even on an empty calendar (i.e., having `0 == length()`).
800 void removeHoliday(const Date& date);
801
802 /// Remove from this calendar the specified `holidayCode` for the
803 /// holiday having the specified `date` if such a holiday having
804 /// `holidayCode` exists. This operation has no effect if `date` is not
805 /// a holiday in this calendar, or if the holiday at `date` does not
806 /// have `holidayCode` associated with it. See {Iterator Invalidation}
807 /// for information regarding which iterators are affected by the use of
808 /// this method. Note that this method is defined for all `date`
809 /// values, not just those that fall within the valid range, and may be
810 /// invoked even on an empty calendar (i.e., having `0 == length()`).
811 void removeHolidayCode(const Date& date, int holidayCode);
812
813 /// Reserve enough space to store at least the specified `numHolidays`
814 /// within this calendar. This method has no effect if
815 /// `numHolidays <= numHolidays()`.
817
818 /// Reserve enough space to store at least the specified
819 /// `numHolidayCodes` within this calendar assuming no additional
820 /// holidays are added to this calendar. This method has no effect if
821 /// `numHolidayCodes <= numHolidayCodesTotal()`.
823
824 /// Set the range of this calendar using the specified `firstDate` and
825 /// `lastDate` as, respectively, the first date and the last date of the
826 /// calendar. Any holiday that is outside the new range and its holiday
827 /// codes are removed. See {Iterator Invalidation} for information
828 /// regarding which iterators are affected by the use of this method.
829 /// The behavior is undefined unless `firstDate <= lastDate`.
830 void setValidRange(const Date& firstDate, const Date& lastDate);
831
832 void unionBusinessDays(const Calendar& other);
833 /// Merge the specified `other` calendar into this calendar such that
834 /// the valid range of this calendar becomes the *union* of the two
835 /// calendars' ranges (or the minimal continuous range spanning the two
836 /// ranges, if the ranges are non-overlapping), the weekend days for
837 /// this calendar become the intersection of those days from the two
838 /// calendars, and the holidays for this calendar become the set of days
839 /// that are a holiday in one of the calendars and a non-business day in
840 /// the other calendar -- i.e., the valid business days of this calendar
841 /// become the union of those of the two original calendar values. For
842 /// each holiday that remains, the resulting holiday codes in this
843 /// calendar will be the union of the corresponding original holiday
844 /// codes. See {Iterator Invalidation} for information regarding which
845 /// iterators are affected by the use of this method.
847
848 void unionNonBusinessDays(const Calendar& other);
849 /// Merge the specified `other` calendar into this calendar such that
850 /// the valid range of this calendar becomes the *union* of the two
851 /// calendars' ranges (or the minimal continuous range spanning the two
852 /// ranges, if the ranges are non-overlapping), and the weekend days
853 /// and holidays for this calendar become the union of those
854 /// (non-business) days from the two calendars -- i.e., the valid
855 /// business days of this calendar become the intersection of those of
856 /// the two calendars after each range is extended to cover the
857 /// resulting one. For each holiday in either calendar, the resulting
858 /// holiday codes in this calendar will be the union of the
859 /// corresponding original holiday codes. See {Iterator Invalidation}
860 /// for information regarding which iterators are affected by the use of
861 /// this method.
863
864 // Aspects
865
866 /// Assign to this object the value read from the specified input
867 /// `stream` using the specified `version` format and return a reference
868 /// to the modifiable `stream`. If `stream` is initially invalid, this
869 /// operation has no effect. If `stream` becomes invalid during this
870 /// operation or if `version` is not supported, this object is
871 /// unaltered. Note that no version is read from `stream`. See the
872 /// `bslx` package-level documentation for more information on BDEX
873 /// streaming of value-semantic types and containers.
874 template <class STREAM>
875 STREAM& bdexStreamIn(STREAM& stream, int version);
876
877 /// Efficiently exchange the value of this object with the value of the
878 /// specified `other` object. This method provides the no-throw
879 /// exception-safety guarantee. The behavior is undefined unless this
880 /// object was created with the same allocator as `other`.
881 void swap(Calendar& other);
882
883 // ACCESSORS
884
885 /// Return an iterator providing non-modifiable access to the first
886 /// business day in this calendar. If this calendar has no valid
887 /// business days, the returned iterator has the same value as that
888 /// returned by `endBusinessDays()`.
890
891 /// Return an iterator providing non-modifiable access to the first
892 /// business day that occurs on or after the specified `date` in this
893 /// calendar. If this calendar has no such business day, the returned
894 /// iterator has the same value as that returned by
895 /// `endBusinessDays(date)`. The behavior is undefined unless `date` is
896 /// within the valid range of this calendar.
898
899 /// Return an iterator providing non-modifiable access to the first
900 /// holiday code for the specified `date` in this calendar. If there is
901 /// no holiday code associated with `date`, the returned iterator has
902 /// the same value as that returned by `endHolidayCodes(date)`. The
903 /// behavior is undefined unless `date` is marked as a holiday in this
904 /// calendar.
906
907 /// Return an iterator providing non-modifiable access to the first
908 /// holiday code for the holiday referenced by the specified `iter`. If
909 /// there is no holiday code associated with the date referenced by
910 /// `iter`, the returned iterator has the same value as that returned by
911 /// `endHolidayCodes(iter)`. The behavior is undefined unless `iter`
912 /// refers to a valid holiday of this calendar.
914 const HolidayConstIterator& iter) const;
915
916 /// Return an iterator providing non-modifiable access to the first
917 /// holiday in this calendar. If this calendar has no holidays, the
918 /// returned iterator has the same value as that returned by
919 /// `endHolidays()`.
921
922 /// Return an iterator providing non-modifiable access to the first
923 /// holiday that occurs on or after the specified `date` in this
924 /// calendar. If this calendar has no such holiday, the returned
925 /// iterator has the same value as that returned by `endHolidays(date)`.
926 /// The behavior is undefined unless `date` is within the valid range
927 /// of this calendar.
928 HolidayConstIterator beginHolidays(const Date& date) const;
929
930 /// Return an iterator providing non-modifiable access to the first
931 /// weekend-days transition in the chronological sequence of
932 /// weekend-days transitions maintained by this calendar. If this
933 /// calendar has no weekend-days transitions, the returned iterator has
934 /// the same value as that returned by `endWeekendDaysTransitions()`.
936
937 /// Return an iterator providing non-modifiable access to the
938 /// past-the-end business day in this calendar.
940
941 /// Return an iterator providing non-modifiable access to the first
942 /// business day that occurs after the specified `date` in this
943 /// calendar. If this calendar has no such business day, the returned
944 /// iterator has the same value as that returned by
945 /// `endBusinessDays()`. The behavior is undefined unless `date` is
946 /// within the valid range of this calendar.
948
949 /// Return an iterator providing non-modifiable access to the
950 /// past-the-end holiday code associated with the specified `date`. The
951 /// behavior is undefined unless `date` is marked as a holiday in this
952 /// calendar.
954
955 /// Return an iterator providing non-modifiable access to the
956 /// past-the-end holiday code associated with the date referenced by
957 /// the specified `iter`. The behavior is undefined unless `iter`
958 /// references a valid holiday in this calendar.
960 endHolidayCodes(const HolidayConstIterator& iter) const;
961
962 /// Return an iterator providing non-modifiable access to the
963 /// past-the-end holiday in the chronological sequence of holidays
964 /// maintained by this calendar.
966
967 /// Return an iterator providing non-modifiable access to the first
968 /// holiday that occurs after the specified `date` in this calendar.
969 /// If this calendar has no such holiday, the returned iterator has the
970 /// same value as that returned by `endHolidays()`. The behavior is
971 /// undefined unless `date` is within the valid range of this calendar.
972 HolidayConstIterator endHolidays(const Date& date) const;
973
974 /// Return an iterator providing non-modifiable access to the
975 /// past-the-end weekend-days transition in the chronological sequence
976 /// of weekend-days transitions maintained by this calendar.
978
979 /// Return a reference providing non-modifiable access to the earliest
980 /// date in the valid range of this calendar. The behavior is
981 /// undefined unless this calendar is non-empty -- i.e., unless
982 /// `1 <= length()`.
983 const Date& firstDate() const;
984
985 /// Load, into the specified `nextBusinessDay`, the date of the first
986 /// business day in this calendar following the specified `date`.
987 /// Return 0 on success -- i.e., if such a business day exists, and a
988 /// non-zero value (with no effect on `nextBusinessDay`) otherwise. The
989 /// behavior is undefined unless `date + 1` is both a valid `bdlt::Date`
990 /// and within the valid range of this calendar.
991 int getNextBusinessDay(Date *nextBusinessDay, const Date& date) const;
992
993 /// Load, into the specified `nextBusinessDay`, the date of the
994 /// specified `nth` business day in this calendar following the
995 /// specified `date`. Return 0 on success -- i.e., if such a business
996 /// day exists, and a non-zero value (with no effect on
997 /// `nextBusinessDay`) otherwise. The behavior is undefined unless
998 /// `date + 1` is both a valid `bdlt::Date` and within the valid range
999 /// of this calendar, and `0 < nth`.
1000 int getNextBusinessDay(Date *nextBusinessDay,
1001 const Date& date,
1002 int nth) const;
1003
1004 /// Return the holiday at the specified `index` in this calendar. For
1005 /// all `index` values from 0 to `numHolidays() - 1` (inclusive), a
1006 /// unique holiday is returned. The mapping of `index` to holiday is
1007 /// invalidated when the set of holidays is modified by an invocation of
1008 /// `addHoliday`, `addHolidayIfInRange`, `intersectBusinessDays`,
1009 /// `intersectNonBusinessDays`, `removeAll`, `removeHoliday`,
1010 /// `setValidRange`, `unionBusinessDays`, or `unionNonBusinessDays`.
1011 /// The behavior is undefined unless `0 <= index < numHolidays()`.
1012 Date holiday(int index) const;
1013
1014 /// Return, for the holiday at the specified `date` in this calendar,
1015 /// the holiday code at the specified `index`. For all `index` values
1016 /// from 0 to `numHolidayCodes(date) - 1` (inclusive), a unique holiday
1017 /// code is returned. The mapping of `index` to holiday code is
1018 /// invalidated when the set of holidays or holiday codes is modified by
1019 /// an invocation of `addHoliday`, `addHolidayCode`,
1020 /// `addHolidayCodeIfInRange`, `addHolidayIfInRange`,
1021 /// `intersectBusinessDays`, `intersectNonBusinessDays`, `removeAll`,
1022 /// `removeHoliday`, `removeHolidayCode`, `setValidRange`,
1023 /// `unionBusinessDays`, or `unionNonBusinessDays`. The behavior is
1024 /// undefined unless `date` is a holiday in this calendar and
1025 /// `0 <= index < numHolidayCodes(date)`. Note that this method
1026 /// facilitates testing and generally should not be used by clients; in
1027 /// particular, using this method to iterate over the holiday codes for
1028 /// `date` is less efficient than using a `HolidayCodeConstIterator`.
1029 int holidayCode(const Date& date, int index) const;
1030
1031 /// Return `true` if the specified `date` is a business day (i.e., not
1032 /// a holiday or weekend day) in this calendar, and `false` otherwise.
1033 /// The behavior is undefined unless `date` is within the valid range of
1034 /// this calendar.
1035 bool isBusinessDay(const Date& date) const;
1036
1037 /// Return `true` if the specified `date` is a holiday in this calendar,
1038 /// and `false` otherwise. The behavior is undefined unless `date` is
1039 /// within the valid range of this calendar.
1040 bool isHoliday(const Date& date) const;
1041
1042 /// Return `true` if the specified `date` is within the valid range of
1043 /// this calendar (i.e., `firstDate() <= date <= lastDate()`), and
1044 /// `false` otherwise. Note that the valid range for a `Calendar` is
1045 /// empty if its length is 0.
1046 bool isInRange(const Date& date) const;
1047
1048 /// Return `true` if the specified `date` is not a business day (i.e.,
1049 /// is either a holiday or weekend day) in this calendar, and `false`
1050 /// otherwise. The behavior is undefined unless `date` is within the
1051 /// valid range of this calendar. Note that:
1052 /// @code
1053 /// !isBusinessDay(date)
1054 /// @endcode
1055 /// returns the same result.
1056 bool isNonBusinessDay(const Date& date) const;
1057
1058 /// Return `true` if the specified `date` falls on a day of the week
1059 /// that is considered a weekend day in this calendar, and `false`
1060 /// otherwise. Note that this method is defined for all `date` values,
1061 /// not just those that fall within the valid range, and may be invoked
1062 /// even on an empty calendar (i.e., having `0 == length()`).
1063 bool isWeekendDay(const Date& date) const;
1064
1065 /// Return `true` if the specified `dayOfWeek` is a weekend day in this
1066 /// calendar, and `false` otherwise. The behavior is undefined unless
1067 /// no weekend-days transitions were added to this calendar via the
1068 /// `addWeekendDaysTransition` method.
1069 bool isWeekendDay(DayOfWeek::Enum dayOfWeek) const;
1070
1071 /// Return a reference providing non-modifiable access to the latest
1072 /// date in the valid range of this calendar. The behavior is
1073 /// undefined unless this calendar is non-empty -- i.e., unless
1074 /// `1 <= length()`.
1075 const Date& lastDate() const;
1076
1077 /// Return the number of days in the valid range of this calendar,
1078 /// which is defined to be 0 if this calendar is empty, and
1079 /// `lastDate() - firstDate() + 1` otherwise.
1080 int length() const;
1081
1082 /// Return the number of days in the valid range of this calendar that
1083 /// are considered business days -- i.e., are neither holidays nor
1084 /// weekend days. Note that
1085 /// `numBusinessDays() == length() - numNonBusinessDays()`.
1086 int numBusinessDays() const;
1087
1088 /// Return the number of days in the specified range
1089 /// `[beginDate .. endDate]` of this calendar that are considered
1090 /// business days -- i.e., are neither holidays nor weekend days. The
1091 /// behavior is undefined unless `beginDate` and `endDate` are within
1092 /// the valid range of this calendar, and `beginDate <= endDate`.
1093 int numBusinessDays(const Date& beginDate, const Date& endDate) const;
1094
1095 /// Return the number of (unique) holiday codes associated with the
1096 /// specified `date` in this calendar if `date` is a holiday in this
1097 /// calendar, and 0 otherwise. The behavior is undefined unless `date`
1098 /// is within the valid range of this calendar.
1099 int numHolidayCodes(const Date& date) const;
1100
1101 /// Return the total number of holiday codes for all holidays in this
1102 /// calendar. Note that this function is used primarily in conjunction
1103 /// with `reserveHolidayCodeCapacity`.
1104 int numHolidayCodesTotal() const;
1105
1106 /// Return the number of days in the valid range of this calendar that
1107 /// are individually marked as holidays, irrespective of whether or not
1108 /// the date is also considered a weekend day.
1109 int numHolidays() const;
1110
1111 /// Return the number of days in the valid range of this calendar that
1112 /// are *not* considered business days -- i.e., are either holidays,
1113 /// weekend days, or both. Note that
1114 /// `numNonBusinessDays() == length() - numBusinessDays()`.
1115 int numNonBusinessDays() const;
1116
1117 /// Return the number of days in the valid range of this calendar that
1118 /// are considered weekend days, irrespective of any designated
1119 /// holidays.
1120 int numWeekendDaysInRange() const;
1121
1122 /// Return the number of weekend-days transitions maintained by this
1123 /// calendar.
1124 int numWeekendDaysTransitions() const;
1125
1126 /// Return a reference providing non-modifiable access to the underlying
1127 /// `PackedCalendar`, which represents the same (mathematical) value as
1128 /// this calendar.
1129 const PackedCalendar& packedCalendar() const;
1130
1131 /// Return an iterator providing non-modifiable access to the last
1132 /// business day in this calendar. If this calendar has no valid
1133 /// business days, the returned iterator has the same value as that
1134 /// returned by `rendBusinessDays()`.
1136
1137 /// Return an iterator providing non-modifiable access to the first
1138 /// business day that occurs on or before the specified `date` in this
1139 /// calendar. If this calendar has no such business day, the returned
1140 /// iterator has the same value as that returned by
1141 /// `rendBusinessDays(date)`. The behavior is undefined unless `date`
1142 /// is within the valid range of this calendar.
1144
1145 /// Return an iterator providing non-modifiable access to the last
1146 /// holiday code associated with the specified `date` in this calendar.
1147 /// If there are no holiday codes associated with `date`, the returned
1148 /// iterator has the same value as that returned by
1149 /// `rendHolidayCodes(date)`. The behavior is undefined unless `date`
1150 /// is marked as a holiday in this calendar.
1152
1153 /// Return an iterator providing non-modifiable access to the last
1154 /// holiday code associated with the holiday referenced by the specified
1155 /// `iter`. If there are no holiday codes associated with the date
1156 /// referenced by `iter`, the returned iterator has the same value as
1157 /// that returned by `rendHolidayCodes(iter)`. The behavior is
1158 /// undefined unless `iter` refers to a valid holiday of this calendar.
1160 rbeginHolidayCodes(const HolidayConstIterator& iter) const;
1161
1162 /// Return an iterator providing non-modifiable access to the last
1163 /// holiday in this calendar. If this calendar has no holidays, the
1164 /// returned iterator has the same value as that returned by
1165 /// `rendHolidays()`.
1167
1168 /// Return an iterator providing non-modifiable access to the first
1169 /// holiday that occurs on or before the specified `date` in this
1170 /// calendar. If this calendar has no such holiday, the returned
1171 /// iterator has the same value as that returned by
1172 /// `rendHolidays(date)`. The behavior is undefined unless `date` is
1173 /// within the valid range of this calendar.
1175
1176 /// Return an iterator providing non-modifiable access to the last
1177 /// weekend-days transition in the chronological sequence of
1178 /// weekend-days transitions maintained by this calendar. If this
1179 /// calendar has no weekend-days transitions, the returned iterator has
1180 /// the same value as that returned by `rendWeekendDaysTransitions()`.
1183
1184 /// Return an iterator providing non-modifiable access to the element
1185 /// one before the first business day in this calendar.
1187
1188 /// Return an iterator providing non-modifiable access to the first
1189 /// business day that occurs before the specified `date` in this
1190 /// calendar. If this calendar has no such business day, the returned
1191 /// iterator has the same value as that returned by
1192 /// `rendBusinessDays()`. The behavior is undefined unless `date` is
1193 /// within the valid range of this calendar.
1195
1196 /// Return an iterator providing non-modifiable access to the element
1197 /// one before the first holiday code associated with the specified
1198 /// `date`. The behavior is undefined unless `date` is marked as a
1199 /// holiday in this calendar.
1201
1202 /// Return an iterator providing non-modifiable access to the element
1203 /// one before the first holiday code associated with the holiday
1204 /// referenced by the specified `iter`. The behavior is undefined
1205 /// unless `iter` references a valid holiday in this calendar.
1207 rendHolidayCodes(const HolidayConstIterator& iter) const;
1208
1209 /// Return an iterator providing non-modifiable access to the element
1210 /// one before the first holiday in this calendar.
1212
1213 /// Return an iterator providing non-modifiable access to the first
1214 /// holiday that occurs before the specified `date` in this calendar.
1215 /// If this calendar has no such holiday, the returned iterator has the
1216 /// same value as that returned by `rendHolidays()`. The behavior is
1217 /// undefined unless `date` is within the valid range of this calendar.
1219
1220 /// Return an iterator providing non-modifiable access to the element
1221 /// one before the first weekend-days transition in the chronological
1222 /// sequence of weekend-days transitions maintained by this calendar.
1225
1226 /// Return the weekend-days transition at the specified `index` in this
1227 /// calendar. For all `index` values from 0 to
1228 /// `numWeekendDaysTransitions() - 1` (inclusive), a unique weekend-days
1229 /// transition is returned. The mapping of `index` to weekend-days
1230 /// transition is invalidated when the set of weekend-days transitions
1231 /// is modified by an invocation of `addWeekendDay`, `addWeekendDays`,
1232 /// `addWeekendDaysTransition`, `intersectBusinessDays`,
1233 /// `intersectNonBusinessDays`, `removeAll`, `unionBusinessDays`, or
1234 /// `unionNonBusinessDays`. The behavior is undefined unless
1235 /// `0 <= index < numWeekendDaysTransitions()`.
1237
1238 // Aspects
1239
1240 /// Return the allocator used by this object to supply memory.
1241 bslma::Allocator *allocator() const;
1242
1243 /// Write this value to the specified output `stream` using the
1244 /// specified `version` format and return a reference to the modifiable
1245 /// `stream`. If `version` is not supported, `stream` is unmodified.
1246 /// Note that `version` is not written to `stream`. See the `bslx`
1247 /// package-level documentation for more information on BDEX streaming
1248 /// of value-semantic types and containers.
1249 template <class STREAM>
1250 STREAM& bdexStreamOut(STREAM& stream, int version) const;
1251
1252 /// Format this object to the specified output `stream` at the (absolute
1253 /// value of) the optionally specified indentation `level` and return a
1254 /// reference to the modifiable `stream`. If `level` is specified,
1255 /// optionally specify `spacesPerLevel`, the number of spaces per
1256 /// indentation level for this and all of its nested objects. If
1257 /// `level` is negative, suppress indentation of the first line. If
1258 /// `spacesPerLevel` is negative, format the entire output on one line,
1259 /// suppressing all but the initial indentation (as governed by
1260 /// `level`). If `stream` is not valid on entry, this operation has no
1261 /// effect.
1262 bsl::ostream& print(bsl::ostream& stream,
1263 int level = 0,
1264 int spacesPerLevel = 4) const;
1265
1266#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE2.22
1267
1268 // DEPRECATED METHODS
1269
1270 /// @deprecated Use @ref maxSupportedBdexVersion(int) instead.
1271 ///
1272 /// Return the most current BDEX streaming version number supported by
1273 /// this class.
1274 static int maxSupportedBdexVersion();
1275
1276#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE2.22
1277
1278#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE3.0
1279
1280 /// Return the date of the first business day following the specified
1281 /// `initialDate`. For dates outside of the range of this calendar,
1282 /// only weekend days are considered non-business days. The behavior
1283 /// is undefined if every day of the week is a weekend day, or if the
1284 /// resulting date would otherwise exceed the value
1285 /// `Date(9999, 12, 31)`.
1286 Date getNextBusinessDay(const Date& initialDate) const;
1287
1288 /// Return the date of the specified `nth` business day following the
1289 /// specified `initialDate`. For dates outside of the range of this
1290 /// calendar, only weekend days are considered non-business days. The
1291 /// behavior is undefined unless `initialDate` is within the valid
1292 /// range and `1 <= nth` (or if every day of the week is a weekend day,
1293 /// or if the resulting date would otherwise exceed the value
1294 /// `Date(9999, 12, 31)`).
1295 Date getNextBusinessDay(const Date& initialDate, int nth) const;
1296
1297#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE3.0
1298
1299};
1300
1301// FREE OPERATORS
1302
1303/// Return `true` if the specified `lhs` and `rhs` calendars have the same
1304/// value, and `false` otherwise. Two calendars have the same value if they
1305/// have the same valid range (or are both empty), the same weekend days,
1306/// the same holidays, and each corresponding pair of holidays has the same
1307/// (ordered) set of associated holiday codes.
1308bool operator==(const Calendar& lhs, const Calendar& rhs);
1309
1310/// Return `true` if the specified `lhs` and `rhs` calendars do not have the
1311/// same value, and `false` otherwise. Two calendars do not have the same
1312/// value if they do not have the same valid range (and are not both empty),
1313/// do not have the same weekend days, do not have the same holidays, or,
1314/// for at least one corresponding pair of holidays, do not have the same
1315/// (ordered) set of associated holiday codes.
1316bool operator!=(const Calendar& lhs, const Calendar& rhs);
1317
1318/// Write the value of the specified `calendar` to the specified output
1319/// `stream`, and return a reference to the modifiable `stream`.
1320bsl::ostream& operator<<(bsl::ostream& stream, const Calendar& calendar);
1321
1322// FREE FUNCTIONS
1323
1324/// Pass the specified `object` to the specified `hashAlg`. This function
1325/// integrates with the `bslh` modular hashing system and effectively
1326/// provides a `bsl::hash` specialization for `Calendar`.
1327template <class HASHALG>
1328void hashAppend(HASHALG& hashAlg, const Calendar& object);
1329
1330/// Exchange the values of the specified `a` and `b` objects. This function
1331/// provides the no-throw exception-safety guarantee if the two objects were
1332/// created with the same allocator and the basic guarantee otherwise.
1333void swap(Calendar& a, Calendar& b);
1334
1335 // ===================================
1336 // class Calendar_BusinessDayConstIter
1337 // ===================================
1338
1339/// Provide read-only, sequential access in increasing (chronological) order
1340/// to the business days in a `Calendar` object.
1341///
1342/// See @ref bdlt_calendar
1344
1345 // DATA
1346 const bdlc::BitArray *d_nonBusinessDays_p; // pointer to the non-business
1347 // day bit array in the
1348 // calendar
1349
1350 Date d_firstDate; // first valid date of the
1351 // calendar
1352
1353 int d_currentOffset; // offset of the date to which
1354 // this iterator is pointing
1355 // (-1 indicates an 'end'
1356 // iterator)
1357
1358 // FRIENDS
1359 friend class Calendar;
1364
1365 private:
1366 // PRIVATE CREATORS
1367
1368 /// Create a business day iterator for a calendar defined by the
1369 /// specified `nonBusinessDays` and `firstDateOfCalendar`. If the
1370 /// specified `endIterFlag` is `false`, then this iterator references
1371 /// the first business day on or after the specified `startDate`;
1372 /// otherwise, this iterator references one business day *past* the
1373 /// first business day on or after `startDate`. If no business day
1374 /// matching the above specification exists, then this iterator
1375 /// references one day past the end of its range. The behavior is
1376 /// undefined unless `startDate` is within the valid range of the
1377 /// calendar defined by `nonBusinessDays` and `firstDateOfCalendar`.
1378 Calendar_BusinessDayConstIter(const bdlc::BitArray& nonBusinessDays,
1379 const Date& firstDateOfCalendar,
1380 const Date& startDate,
1381 bool endIterFlag);
1382
1383 public:
1384 // PUBLIC TYPES
1386 typedef int difference_type;
1388
1389 /// The star operator returns a `PackedCalendar_DateRef` *by* *value*.
1391
1392 typedef bsl::bidirectional_iterator_tag iterator_category;
1393
1394 // CREATORS
1395
1396 /// Create an iterator having the value of the specified `original`
1397 /// iterator.
1399 const Calendar_BusinessDayConstIter& original);
1400
1401 /// Destroy this object.
1403
1404 // MANIPULATORS
1405
1406 /// Assign to this iterator the value of the specified `rhs` iterator,
1407 /// and return a reference providing modifiable access to this object.
1410
1411 /// Advance this iterator to refer to the next business day in the
1412 /// associated calendar, and return a reference providing modifiable
1413 /// access to this object. The behavior is undefined unless, on entry,
1414 /// this iterator references a valid business day.
1416
1417 /// Regress this iterator to refer to the previous business day in the
1418 /// associated calendar, and return a reference providing modifiable
1419 /// access to this object. The behavior is undefined unless, on entry,
1420 /// this iterator references a valid business day that is not the first
1421 /// business day for the associated calendar.
1423
1424 // ACCESSORS
1425
1426 /// Return a `PackedCalendar_DateRef` object that contains the date
1427 /// value of the business day referenced by this iterator.
1429
1430 /// Return a date proxy for the business day referenced by this
1431 /// iterator.
1433};
1434
1435// FREE OPERATORS
1436
1437/// Return `true` if the specified `lhs` and `rhs` iterators refer to the
1438/// same element in the same calendar, and `false` otherwise. The behavior
1439/// is undefined unless `lhs` and `rhs` both iterate over the same calendar.
1440bool operator==(const Calendar_BusinessDayConstIter& lhs,
1442
1443/// Return `true` if the specified `lhs` and `rhs` iterators do not refer to
1444/// the same element in the same calendar, and `false` otherwise. The
1445/// behavior is undefined unless `lhs` and `rhs` both iterate over the same
1446/// calendar.
1447bool operator!=(const Calendar_BusinessDayConstIter& lhs,
1449
1450/// Advance the specified `iterator` to refer to the next business day in
1451/// the associated calendar, and return the previous value of `iterator`.
1452/// The behavior is undefined unless, on entry, `iterator` references a
1453/// valid business day.
1455 Calendar_BusinessDayConstIter& iterator, int);
1456
1457/// Regress the specified `iterator` to refer to the previous business day
1458/// in the associated calendar, and return the previous value of `iterator`.
1459/// The behavior is undefined unless, on entry, `iterator` references a
1460/// valid business day that is not the first business day for the associated
1461/// calendar.
1463 Calendar_BusinessDayConstIter& iterator, int);
1464
1465// ============================================================================
1466// INLINE DEFINITIONS
1467// ============================================================================
1468
1469 // --------------
1470 // class Calendar
1471 // --------------
1472
1473// CLASS METHODS
1474
1475 // Aspects
1476
1477inline
1479{
1480 return PackedCalendar::maxSupportedBdexVersion(versionSelector);
1481}
1482
1483// MANIPULATORS
1484inline
1486{
1487 Calendar(rhs, d_packedCalendar.allocator()).swap(*this);
1488 return *this;
1489}
1490
1491inline
1493{
1494 Calendar(rhs, d_packedCalendar.allocator()).swap(*this);
1495 return *this;
1496}
1497
1498inline
1499int Calendar::addHolidayCodeIfInRange(const Date& date, int holidayCode)
1500{
1501 if (isInRange(date)) {
1503 return 0; // RETURN
1504 }
1505 return -1;
1506}
1507
1508inline
1510{
1511 if (isInRange(date)) {
1512 addHoliday(date);
1513 return 0; // RETURN
1514 }
1515 return -1;
1516}
1517
1518inline
1520 const DayOfWeekSet& weekendDays)
1521{
1522 d_packedCalendar.addWeekendDaysTransition(startDate, weekendDays);
1523 synchronizeCache();
1524}
1525
1526inline
1528{
1529 d_packedCalendar.intersectBusinessDays(other);
1530 synchronizeCache();
1531}
1532
1533inline
1535{
1536 intersectBusinessDays(other.d_packedCalendar);
1537}
1538
1539inline
1541{
1542 d_packedCalendar.intersectNonBusinessDays(other);
1543 synchronizeCache();
1544}
1545
1546inline
1548{
1549 intersectNonBusinessDays(other.d_packedCalendar);
1550}
1551
1552inline
1554{
1555 d_packedCalendar.removeAll();
1556 d_nonBusinessDays.removeAll();
1557}
1558
1559inline
1561{
1562 d_packedCalendar.removeHoliday(date);
1563
1564 if (true == isInRange(date) && false == isWeekendDay(date)) {
1565 d_nonBusinessDays.assign0(date - firstDate());
1566 }
1567}
1568
1569inline
1570void Calendar::removeHolidayCode(const Date& date, int holidayCode)
1571{
1572 d_packedCalendar.removeHolidayCode(date, holidayCode);
1573}
1574
1575inline
1577{
1578 d_packedCalendar.reserveHolidayCapacity(numHolidays);
1579}
1580
1581inline
1583{
1585}
1586
1587inline
1588void Calendar::setValidRange(const Date& firstDate, const Date& lastDate)
1589{
1593
1594 if (firstDate <= lastDate) {
1595 // For backwards compatibility, 'firstDate > lastDate' results in an
1596 // empty calendar (when asserts are not enabled).
1597
1598 d_nonBusinessDays.reserveCapacity(lastDate - firstDate + 1);
1599 }
1600
1601 d_packedCalendar.setValidRange(firstDate, lastDate);
1602
1603 synchronizeCache();
1604}
1605
1606inline
1608{
1609 unionBusinessDays(other.d_packedCalendar);
1610}
1611
1612inline
1614{
1615 unionNonBusinessDays(other.d_packedCalendar);
1616}
1617
1618 // Aspects
1619
1620template <class STREAM>
1621STREAM& Calendar::bdexStreamIn(STREAM& stream, int version)
1622{
1623 if (stream) {
1624 PackedCalendar inCal(allocator());
1625 inCal.bdexStreamIn(stream, version);
1626 if (!stream) {
1627 return stream; // RETURN
1628 }
1629 d_nonBusinessDays.reserveCapacity(inCal.length());
1630 d_packedCalendar.swap(inCal);
1631 synchronizeCache();
1632 }
1633 return stream;
1634}
1635
1636inline
1638{
1639 // 'swap' is undefined for objects with non-equal allocators.
1641 BSLS_ASSERT(d_packedCalendar.allocator() ==
1642 other.d_packedCalendar.allocator());
1644 bslalg::SwapUtil::swap(&d_packedCalendar, &other.d_packedCalendar);
1645 bslalg::SwapUtil::swap(&d_nonBusinessDays, &other.d_nonBusinessDays);
1646}
1647
1648// ACCESSORS
1649inline
1651{
1652 if (length()) {
1653 return Calendar_BusinessDayConstIter(d_nonBusinessDays,
1654 firstDate(),
1655 firstDate(),
1656 false); // RETURN
1657 }
1658
1659 return endBusinessDays();
1660}
1661
1662inline
1665{
1669
1670 return Calendar_BusinessDayConstIter(d_nonBusinessDays,
1671 firstDate(),
1672 date,
1673 false);
1674}
1675
1676inline
1679{
1680 return d_packedCalendar.beginHolidayCodes(date);
1681}
1682
1683inline
1686{
1687 return d_packedCalendar.beginHolidayCodes(iter);
1688}
1689
1690inline
1692{
1693 return d_packedCalendar.beginHolidays();
1694}
1695
1696inline
1698{
1699 return d_packedCalendar.beginHolidays(date);
1700}
1701
1702inline
1705{
1706 return d_packedCalendar.beginWeekendDaysTransitions();
1707}
1708
1709inline
1711{
1712 if (length()) {
1713 return BusinessDayConstIterator(d_nonBusinessDays,
1714 firstDate(),
1715 lastDate(),
1716 true); // RETURN
1717 }
1718 return BusinessDayConstIterator(d_nonBusinessDays,
1719 Date() + 1,
1720 Date(),
1721 true);
1722}
1723
1724inline
1727{
1731
1732 return BusinessDayConstIterator(d_nonBusinessDays,
1733 firstDate(),
1734 date,
1735 true);
1736}
1737
1738inline
1741{
1742 return d_packedCalendar.endHolidayCodes(date);
1743}
1744
1745inline
1748{
1749 return d_packedCalendar.endHolidayCodes(iter);
1750}
1751
1752inline
1754{
1755 return d_packedCalendar.endHolidays();
1756}
1757
1758inline
1760{
1761 return d_packedCalendar.endHolidays(date);
1762}
1763
1764inline
1767{
1768 return d_packedCalendar.endWeekendDaysTransitions();
1769}
1770
1771inline
1773{
1774 return d_packedCalendar.firstDate();
1775}
1776
1777inline
1778int Calendar::getNextBusinessDay(Date *nextBusinessDay, const Date& date) const
1779{
1781 BSLS_ASSERT_SAFE(nextBusinessDay);
1782 BSLS_ASSERT_SAFE(Date(9999, 12, 31) > date);
1783 BSLS_ASSERT_SAFE(isInRange(date + 1));
1785
1786 enum { e_SUCCESS = 0, e_FAILURE = 1 };
1787
1788 int offset = static_cast<int>(
1789 d_nonBusinessDays.find0AtMinIndex(date + 1 - firstDate()));
1790 if (0 <= offset) {
1791 *nextBusinessDay = firstDate() + offset;
1792 return e_SUCCESS; // RETURN
1793 }
1794
1795 return e_FAILURE;
1796}
1797
1798
1799inline
1800Date Calendar::holiday(int index) const
1801{
1802 return d_packedCalendar.holiday(index);
1803}
1804
1805inline
1806int Calendar::holidayCode(const Date& date, int index) const
1807{
1808 return d_packedCalendar.holidayCode(date, index);
1809}
1810
1811inline
1812bool Calendar::isBusinessDay(const Date& date) const
1813{
1814 return !isNonBusinessDay(date);
1815}
1816
1817inline
1818bool Calendar::isHoliday(const Date& date) const
1819{
1820 return d_packedCalendar.isHoliday(date);
1821}
1822
1823inline
1824bool Calendar::isInRange(const Date& date) const
1825{
1826 return d_packedCalendar.isInRange(date);
1827}
1828
1829inline
1830bool Calendar::isNonBusinessDay(const Date& date) const
1831{
1835
1836 return d_nonBusinessDays[date - firstDate()];
1837}
1838
1839inline
1840bool Calendar::isWeekendDay(const Date& date) const
1841{
1842 return d_packedCalendar.isWeekendDay(date);
1843}
1844
1845inline
1847{
1848 return d_packedCalendar.isWeekendDay(dayOfWeek);
1849}
1850
1851inline
1853{
1854 return d_packedCalendar.lastDate();
1855}
1856
1857inline
1859{
1860 return static_cast<int>(d_nonBusinessDays.length());
1861}
1862
1863inline
1865{
1866 return static_cast<int>(d_nonBusinessDays.num0());
1867}
1868
1869inline
1870int Calendar::numBusinessDays(const Date& beginDate, const Date& endDate) const
1871{
1873 BSLS_ASSERT_SAFE(isInRange(beginDate));
1874 BSLS_ASSERT_SAFE(isInRange(endDate));
1875 BSLS_ASSERT_SAFE(beginDate <= endDate);
1877
1878 return static_cast<int>(d_nonBusinessDays.num0(beginDate - firstDate(),
1879 endDate - firstDate() + 1));
1880}
1881
1882inline
1883int Calendar::numHolidayCodes(const Date& date) const
1884{
1885 return d_packedCalendar.numHolidayCodes(date);
1886}
1887
1888inline
1890{
1891 return d_packedCalendar.numHolidayCodesTotal();
1892}
1893
1894inline
1896{
1897 return d_packedCalendar.numHolidays();
1898}
1899
1900inline
1902{
1903 return static_cast<int>(d_nonBusinessDays.num1());
1904}
1905
1906inline
1908{
1909 return d_packedCalendar.numWeekendDaysInRange();
1910}
1911
1912inline
1914{
1915 return d_packedCalendar.numWeekendDaysTransitions();
1916}
1917
1918inline
1920{
1921 return d_packedCalendar;
1922}
1923
1924inline
1929
1930inline
1933{
1935
1937}
1938
1939inline
1942{
1943 return d_packedCalendar.rbeginHolidayCodes(date);
1944}
1945
1946inline
1949{
1950 return d_packedCalendar.rbeginHolidayCodes(iter);
1951}
1952
1953inline
1955{
1956 return d_packedCalendar.rbeginHolidays();
1957}
1958
1959inline
1962{
1963 return d_packedCalendar.rbeginHolidays(date);
1964}
1965
1966inline
1969{
1970 return d_packedCalendar.rbeginWeekendDaysTransitions();
1971}
1972
1973inline
1978
1979inline
1982{
1984
1986}
1987
1988inline
1991{
1992 return d_packedCalendar.rendHolidayCodes(date);
1993}
1994
1995inline
1998{
1999 return d_packedCalendar.rendHolidayCodes(iter);
2000}
2001
2002inline
2004{
2005 return d_packedCalendar.rendHolidays();
2006}
2007
2008inline
2010 Calendar::rendHolidays(const Date& date) const
2011{
2012 return d_packedCalendar.rendHolidays(date);
2013}
2014
2015inline
2018{
2019 return d_packedCalendar.rendWeekendDaysTransitions();
2020}
2021
2022inline
2025{
2026 return d_packedCalendar.weekendDaysTransition(index);
2027}
2028
2029 // Aspects
2030
2031inline
2033{
2034 return d_packedCalendar.allocator();
2035}
2036
2037template <class STREAM>
2038inline
2039STREAM& Calendar::bdexStreamOut(STREAM& stream, int version) const
2040{
2041
2042 d_packedCalendar.bdexStreamOut(stream, version);
2043 return stream;
2044}
2045
2046inline
2047bsl::ostream& Calendar::print(bsl::ostream& stream,
2048 int level,
2049 int spacesPerLevel) const
2050{
2051 return d_packedCalendar.print(stream, level, spacesPerLevel);
2052}
2053
2054#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE2.22
2055
2056// DEPRECATED METHODS
2057inline
2059{
2060 return 1;
2061}
2062
2063#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE2.22
2064
2065} // close package namespace
2066
2067// FREE OPERATORS
2068inline
2069bool bdlt::operator==(const Calendar& lhs, const Calendar& rhs)
2070{
2071 return lhs.d_packedCalendar == rhs.d_packedCalendar;
2072}
2073
2074inline
2075bool bdlt::operator!=(const Calendar& lhs, const Calendar& rhs)
2076{
2077 return lhs.d_packedCalendar != rhs.d_packedCalendar;
2078}
2079
2080inline
2081bsl::ostream& bdlt::operator<<(bsl::ostream& stream, const Calendar& calendar)
2082{
2083 calendar.print(stream, 0, -1);
2084 return stream;
2085}
2086
2087// FREE FUNCTIONS
2088template <class HASHALG>
2089inline
2090void bdlt::hashAppend(HASHALG& hashAlg, const Calendar& object)
2091{
2092 using ::BloombergLP::bslh::hashAppend;
2093 hashAppend(hashAlg, object.d_packedCalendar);
2094}
2095
2096namespace bdlt {
2097
2098 // -----------------------------------
2099 // class Calendar_BusinessDayConstIter
2100 // -----------------------------------
2101
2102// CREATORS
2103inline
2104Calendar_BusinessDayConstIter::Calendar_BusinessDayConstIter(
2105 const Calendar_BusinessDayConstIter& original)
2106: d_nonBusinessDays_p(original.d_nonBusinessDays_p)
2107, d_firstDate(original.d_firstDate)
2108, d_currentOffset(original.d_currentOffset)
2109{
2110}
2111
2112inline
2116
2117// MANIPULATORS
2118inline
2121{
2122 d_nonBusinessDays_p = rhs.d_nonBusinessDays_p;
2123 d_firstDate = rhs.d_firstDate;
2124 d_currentOffset = rhs.d_currentOffset;
2125 return *this;
2126}
2127
2128inline
2130{
2131 BSLS_ASSERT_SAFE(d_currentOffset >= 0);
2132
2133 d_currentOffset = static_cast<int>(
2134 d_nonBusinessDays_p->find0AtMinIndex(d_currentOffset + 1));
2135 return *this;
2136}
2137
2138inline
2140{
2141 if (-1 == d_currentOffset) {
2142 d_currentOffset = static_cast<int>(d_nonBusinessDays_p->
2143 find0AtMaxIndex(0, d_nonBusinessDays_p->length()));
2144 }
2145 else {
2146 d_currentOffset = static_cast<int>(d_nonBusinessDays_p->
2147 find0AtMaxIndex(0, d_currentOffset));
2148 }
2149
2150 BSLS_ASSERT_SAFE(0 <= d_currentOffset);
2151
2152 return *this;
2153}
2154
2155inline
2157 Calendar_BusinessDayConstIter& iterator, int)
2158{
2159 Calendar_BusinessDayConstIter tmp(iterator);
2160 ++iterator;
2161 return tmp;
2162}
2163
2164inline
2166 Calendar_BusinessDayConstIter& iterator, int)
2167{
2168 Calendar_BusinessDayConstIter tmp(iterator);
2169 --iterator;
2170 return tmp;
2171}
2172
2173// ACCESSORS
2174inline
2176{
2177 return PackedCalendar_DateRef(d_firstDate + d_currentOffset);
2178}
2179
2180inline
2185
2186} // close package namespace
2187
2188// FREE OPERATORS
2189inline
2190bool bdlt::operator==(const Calendar_BusinessDayConstIter& lhs,
2191 const Calendar_BusinessDayConstIter& rhs)
2192{
2193 BSLS_ASSERT_SAFE(lhs.d_nonBusinessDays_p == rhs.d_nonBusinessDays_p);
2194
2195 return lhs.d_firstDate == rhs.d_firstDate
2196 && lhs.d_currentOffset == rhs.d_currentOffset;
2197}
2198
2199inline
2200bool bdlt::operator!=(const Calendar_BusinessDayConstIter& lhs,
2201 const Calendar_BusinessDayConstIter& rhs)
2202{
2203 BSLS_ASSERT_SAFE(lhs.d_nonBusinessDays_p == rhs.d_nonBusinessDays_p);
2204
2205 return lhs.d_firstDate != rhs.d_firstDate
2206 || lhs.d_currentOffset != rhs.d_currentOffset;
2207}
2208
2209
2210
2211// TRAITS
2212
2213namespace bslma {
2214
2215template <>
2217
2218} // close namespace bslma
2219
2220
2221#endif
2222
2223// ----------------------------------------------------------------------------
2224// Copyright 2018 Bloomberg Finance L.P.
2225//
2226// Licensed under the Apache License, Version 2.0 (the "License");
2227// you may not use this file except in compliance with the License.
2228// You may obtain a copy of the License at
2229//
2230// http://www.apache.org/licenses/LICENSE-2.0
2231//
2232// Unless required by applicable law or agreed to in writing, software
2233// distributed under the License is distributed on an "AS IS" BASIS,
2234// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2235// See the License for the specific language governing permissions and
2236// limitations under the License.
2237// ----------------------------- END-OF-FILE ----------------------------------
2238
2239/** @} */
2240/** @} */
2241/** @} */
Definition bdlc_bitarray.h:521
bsl::size_t num0(bsl::size_t begin=0, bsl::size_t end=k_INVALID_INDEX) const
Definition bdlc_bitarray.h:1821
bsl::size_t length() const
Return the number of bits in this array.
Definition bdlc_bitarray.h:1815
bsl::size_t num1(bsl::size_t begin=0, bsl::size_t end=k_INVALID_INDEX) const
Definition bdlc_bitarray.h:1833
void removeAll()
Definition bdlc_bitarray.h:1578
bsl::size_t find0AtMinIndex(bsl::size_t begin=0, bsl::size_t end=k_INVALID_INDEX) const
Definition bdlc_bitarray.h:1761
void assign0(bsl::size_t index)
Definition bdlc_bitarray.h:1413
void reserveCapacity(bsl::size_t numBits)
Definition bdlc_bitarray.h:1586
Definition bdlt_calendarreverseiteratoradapter.h:298
Definition bdlt_calendar.h:1343
friend bool operator==(const Calendar_BusinessDayConstIter &, const Calendar_BusinessDayConstIter &)
Date value_type
Definition bdlt_calendar.h:1385
int difference_type
Definition bdlt_calendar.h:1386
friend bool operator!=(const Calendar_BusinessDayConstIter &, const Calendar_BusinessDayConstIter &)
PackedCalendar_DateRef operator*() const
Definition bdlt_calendar.h:2175
PackedCalendar_DateProxy pointer
Definition bdlt_calendar.h:1387
PackedCalendar_DateRef reference
The star operator returns a PackedCalendar_DateRef by value.
Definition bdlt_calendar.h:1390
Calendar_BusinessDayConstIter & operator++()
Definition bdlt_calendar.h:2129
Calendar_BusinessDayConstIter & operator=(const Calendar_BusinessDayConstIter &rhs)
Definition bdlt_calendar.h:2119
PackedCalendar_DateProxy operator->() const
Definition bdlt_calendar.h:2181
bsl::bidirectional_iterator_tag iterator_category
Definition bdlt_calendar.h:1392
~Calendar_BusinessDayConstIter()
Destroy this object.
Definition bdlt_calendar.h:2113
Calendar_BusinessDayConstIter & operator--()
Definition bdlt_calendar.h:2139
Definition bdlt_calendar.h:569
int getNextBusinessDay(Date *nextBusinessDay, const Date &date, int nth) const
BusinessDayConstIterator endBusinessDays() const
Definition bdlt_calendar.h:1710
WeekendDaysTransitionConstIterator endWeekendDaysTransitions() const
Definition bdlt_calendar.h:1766
int numHolidayCodesTotal() const
Definition bdlt_calendar.h:1889
HolidayConstIterator beginHolidays() const
Definition bdlt_calendar.h:1691
PackedCalendar::WeekendDaysTransitionConstReverseIterator WeekendDaysTransitionConstReverseIterator
Definition bdlt_calendar.h:627
void removeHoliday(const Date &date)
Definition bdlt_calendar.h:1560
void unionBusinessDays(const Calendar &other)
Definition bdlt_calendar.h:1607
Calendar_BusinessDayConstIter BusinessDayConstIterator
Definition bdlt_calendar.h:606
int numNonBusinessDays() const
Definition bdlt_calendar.h:1901
static int maxSupportedBdexVersion()
Definition bdlt_calendar.h:2058
void unionNonBusinessDays(const Calendar &other)
Definition bdlt_calendar.h:1613
HolidayConstReverseIterator rendHolidays() const
Definition bdlt_calendar.h:2003
void addWeekendDay(DayOfWeek::Enum weekendDay)
Date getNextBusinessDay(const Date &initialDate) const
BusinessDayConstReverseIterator rendBusinessDays() const
Definition bdlt_calendar.h:1974
HolidayCodeConstReverseIterator rendHolidayCodes(const Date &date) const
Definition bdlt_calendar.h:1990
Date getNextBusinessDay(const Date &initialDate, int nth) const
PackedCalendar::WeekendDaysTransition WeekendDaysTransition
Definition bdlt_calendar.h:621
void setValidRange(const Date &firstDate, const Date &lastDate)
Definition bdlt_calendar.h:1588
PackedCalendar::HolidayCodeConstIterator HolidayCodeConstIterator
Definition bdlt_calendar.h:610
void removeHolidayCode(const Date &date, int holidayCode)
Definition bdlt_calendar.h:1570
bool isInRange(const Date &date) const
Definition bdlt_calendar.h:1824
HolidayCodeConstIterator beginHolidayCodes(const Date &date) const
Definition bdlt_calendar.h:1678
WeekendDaysTransitionConstReverseIterator rendWeekendDaysTransitions() const
Definition bdlt_calendar.h:2017
void addDay(const Date &date)
void addHoliday(const Date &date)
int holidayCode(const Date &date, int index) const
Definition bdlt_calendar.h:1806
HolidayCodeConstIterator endHolidayCodes(const Date &date) const
Definition bdlt_calendar.h:1740
void addWeekendDaysTransition(const Date &startDate, const DayOfWeekSet &weekendDays)
Definition bdlt_calendar.h:1519
PackedCalendar::HolidayConstIterator HolidayConstIterator
Definition bdlt_calendar.h:608
Calendar(bslma::Allocator *basicAllocator=0)
WeekendDaysTransition weekendDaysTransition(int index) const
Definition bdlt_calendar.h:2024
int getNextBusinessDay(Date *nextBusinessDay, const Date &date) const
Definition bdlt_calendar.h:1778
void unionNonBusinessDays(const PackedCalendar &other)
int numHolidayCodes(const Date &date) const
Definition bdlt_calendar.h:1883
bool isNonBusinessDay(const Date &date) const
Definition bdlt_calendar.h:1830
friend void hashAppend(HASHALG &hashAlg, const Calendar &)
HolidayConstReverseIterator rbeginHolidays() const
Definition bdlt_calendar.h:1954
WeekendDaysTransitionConstIterator beginWeekendDaysTransitions() const
Definition bdlt_calendar.h:1704
void addHolidayCode(const Date &date, int holidayCode)
BusinessDayConstReverseIterator rbeginBusinessDays() const
Definition bdlt_calendar.h:1925
void reserveHolidayCodeCapacity(int numHolidayCodes)
Definition bdlt_calendar.h:1582
const Date & firstDate() const
Definition bdlt_calendar.h:1772
bool isHoliday(const Date &date) const
Definition bdlt_calendar.h:1818
const Date & lastDate() const
Definition bdlt_calendar.h:1852
Calendar(const Calendar &original, bslma::Allocator *basicAllocator=0)
BusinessDayConstIterator beginBusinessDays() const
Definition bdlt_calendar.h:1650
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlt_calendar.h:2032
int numBusinessDays() const
Definition bdlt_calendar.h:1864
WeekendDaysTransitionConstReverseIterator rbeginWeekendDaysTransitions() const
Definition bdlt_calendar.h:1968
~Calendar()
Destroy this object.
int addHolidayCodeIfInRange(const Date &date, int holidayCode)
Definition bdlt_calendar.h:1499
STREAM & bdexStreamIn(STREAM &stream, int version)
Definition bdlt_calendar.h:1621
void intersectBusinessDays(const Calendar &other)
Definition bdlt_calendar.h:1534
void addWeekendDays(const DayOfWeekSet &weekendDays)
HolidayConstIterator endHolidays() const
Definition bdlt_calendar.h:1753
const PackedCalendar & packedCalendar() const
Definition bdlt_calendar.h:1919
Date holiday(int index) const
Definition bdlt_calendar.h:1800
void intersectNonBusinessDays(const Calendar &other)
Definition bdlt_calendar.h:1547
PackedCalendar::HolidayCodeConstReverseIterator HolidayCodeConstReverseIterator
Definition bdlt_calendar.h:619
void swap(Calendar &other)
Definition bdlt_calendar.h:1637
int length() const
Definition bdlt_calendar.h:1858
bool isWeekendDay(const Date &date) const
Definition bdlt_calendar.h:1840
void reserveHolidayCapacity(int numHolidays)
Definition bdlt_calendar.h:1576
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
Definition bdlt_calendar.h:2047
int numWeekendDaysTransitions() const
Definition bdlt_calendar.h:1913
STREAM & bdexStreamOut(STREAM &stream, int version) const
Definition bdlt_calendar.h:2039
PackedCalendar::WeekendDaysTransitionConstIterator WeekendDaysTransitionConstIterator
Definition bdlt_calendar.h:624
HolidayCodeConstReverseIterator rbeginHolidayCodes(const Date &date) const
Definition bdlt_calendar.h:1941
bool isBusinessDay(const Date &date) const
Definition bdlt_calendar.h:1812
Calendar(const bdlt::PackedCalendar &packedCalendar, bslma::Allocator *basicAllocator=0)
PackedCalendar::HolidayConstReverseIterator HolidayConstReverseIterator
Definition bdlt_calendar.h:616
friend bool operator==(const Calendar &, const Calendar &)
Calendar & operator=(const Calendar &rhs)
Definition bdlt_calendar.h:1485
int numWeekendDaysInRange() const
Definition bdlt_calendar.h:1907
int numHolidays() const
Definition bdlt_calendar.h:1895
void unionBusinessDays(const PackedCalendar &other)
int addHolidayIfInRange(const Date &date)
Definition bdlt_calendar.h:1509
CalendarReverseIteratorAdapter< BusinessDayConstIterator > BusinessDayConstReverseIterator
Definition bdlt_calendar.h:613
friend bool operator!=(const Calendar &, const Calendar &)
Calendar(const Date &firstDate, const Date &lastDate, bslma::Allocator *basicAllocator=0)
void removeAll()
Definition bdlt_calendar.h:1553
Definition bdlt_date.h:294
Definition bdlt_dayofweekset.h:398
Definition bdlt_packedcalendar.h:1436
Definition bdlt_packedcalendar.h:1474
Definition bdlt_packedcalendar.h:1628
Definition bdlt_packedcalendar.h:1510
Definition bdlt_packedcalendar.h:592
void reserveHolidayCodeCapacity(int numHolidayCodes)
Definition bdlt_packedcalendar.h:2343
HolidayConstReverseIterator rbeginHolidays() const
Definition bdlt_packedcalendar.h:3106
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:2927
int numHolidays() const
Definition bdlt_packedcalendar.h:3059
int numHolidayCodesTotal() const
Definition bdlt_packedcalendar.h:3053
void removeHoliday(const Date &date)
WeekendDaysTransitionConstReverseIterator rendWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:3180
HolidayCodeConstReverseIterator rendHolidayCodes(const Date &date) const
Definition bdlt_packedcalendar.h:3146
int holidayCode(const Date &date, int index) const
Definition bdlt_packedcalendar.h:2962
WeekendDaysTransitionConstIterator endWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:2921
WeekendDaysTransitionSequence::const_iterator WeekendDaysTransitionConstIterator
Definition bdlt_packedcalendar.h:645
void removeHolidayCode(const Date &date, int holidayCode)
STREAM & bdexStreamIn(STREAM &stream, int version)
Definition bdlt_packedcalendar.h:2353
void addWeekendDaysTransition(const Date &startDate, const DayOfWeekSet &weekendDays)
void reserveHolidayCapacity(int numHolidays)
Definition bdlt_packedcalendar.h:2334
HolidayConstIterator beginHolidays() const
Definition bdlt_packedcalendar.h:2850
const Date & lastDate() const
Definition bdlt_packedcalendar.h:3033
bool isHoliday(const Date &date) const
Definition bdlt_packedcalendar.h:2988
HolidayCodeConstReverseIterator rbeginHolidayCodes(const Date &date) const
Definition bdlt_packedcalendar.h:3088
void swap(PackedCalendar &other)
void intersectNonBusinessDays(const PackedCalendar &other)
WeekendDaysTransition weekendDaysTransition(int index) const
Definition bdlt_packedcalendar.h:3188
HolidayConstIterator endHolidays() const
Definition bdlt_packedcalendar.h:2901
bool isInRange(const Date &date) const
Definition bdlt_packedcalendar.h:3003
void intersectBusinessDays(const PackedCalendar &other)
bsl::reverse_iterator< WeekendDaysTransitionSequence::const_iterator > WeekendDaysTransitionConstReverseIterator
Definition bdlt_packedcalendar.h:649
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlt_packedcalendar.h:3199
int length() const
Definition bdlt_packedcalendar.h:3041
bdlt::Date holiday(int index) const
Definition bdlt_packedcalendar.h:2953
static int maxSupportedBdexVersion()
Definition bdlt_packedcalendar.h:3287
STREAM & bdexStreamOut(STREAM &stream, int version) const
Definition bdlt_packedcalendar.h:3205
int numWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:3065
WeekendDaysTransitionConstIterator beginWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:2870
HolidayConstReverseIterator rendHolidays() const
Definition bdlt_packedcalendar.h:3164
WeekendDaysTransitionConstReverseIterator rbeginWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:3122
bool isWeekendDay(const Date &date) const
int numHolidayCodes(const Date &date) const
Definition bslstl_pair.h:1210
static void swap(T *a, T *b)
Definition bslalg_swaputil.h:194
Definition bslma_allocator.h:457
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_PRECONDITIONS_END()
Definition bsls_preconditions.h:131
#define BSLS_PRECONDITIONS_BEGIN()
Definition bsls_preconditions.h:130
void hashAppend(HASH_ALGORITHM &hashAlg, const baljsn::EncoderTestAddress &object)
Definition baljsn_encoder_testtypes.h:9236
Definition bbldc_basicisma30360.h:112
Calendar_BusinessDayConstIter operator++(Calendar_BusinessDayConstIter &iterator, int)
Definition bdlt_calendar.h:2156
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:2165
Definition balxml_encoderoptions.h:68
Enum
Enumerated day-of-week values.
Definition bdlt_dayofweek.h:123
Definition bslma_usesbslmaallocator.h:343