BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlt_packedcalendar.h
Go to the documentation of this file.
1/// @file bdlt_packedcalendar.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlt_packedcalendar.h -*-C++-*-
8#ifndef INCLUDED_BDLT_PACKEDCALENDAR
9#define INCLUDED_BDLT_PACKEDCALENDAR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlt_packedcalendar bdlt_packedcalendar
15/// @brief Provide a compact repository for weekend/holiday information.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlt
19/// @{
20/// @addtogroup bdlt_packedcalendar
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlt_packedcalendar-purpose"> Purpose</a>
25/// * <a href="#bdlt_packedcalendar-classes"> Classes </a>
26/// * <a href="#bdlt_packedcalendar-description"> Description </a>
27/// * <a href="#bdlt_packedcalendar-weekend-days-and-weekend-days-transitions"> Weekend Days and Weekend-Days Transitions </a>
28/// * <a href="#bdlt_packedcalendar-nested-iterators"> Nested Iterators </a>
29/// * <a href="#bdlt_packedcalendar-iterator-invalidation"> Iterator Invalidation </a>
30/// * <a href="#bdlt_packedcalendar-performance-and-exception-safety-guarantees"> Performance and Exception-Safety Guarantees </a>
31/// * <a href="#bdlt_packedcalendar-usage"> Usage </a>
32/// * <a href="#bdlt_packedcalendar-example-1-populating-packed-calendars"> Example 1: Populating Packed Calendars </a>
33/// * <a href="#bdlt_packedcalendar-example-2-using-packed-calendars"> Example 2: Using Packed Calendars </a>
34///
35/// # Purpose {#bdlt_packedcalendar-purpose}
36/// Provide a compact repository for weekend/holiday information.
37///
38/// # Classes {#bdlt_packedcalendar-classes}
39///
40/// - bdlt::PackedCalendar: compact repository of weekend/holiday information
41///
42/// @see bdlt_calendar
43///
44/// # Description {#bdlt_packedcalendar-description}
45/// This component provides a value-semantic class,
46/// `bdlt::PackedCalendar`, that represents weekend and holiday information over
47/// a *valid* *range* of dates. A `bdlt::PackedCalendar` is an approximation to
48/// the same *mathematical* type, and is capable of representing the same subset
49/// of *mathematical* values, as a `bdlt::Calendar`.
50///
51/// But unlike `bdlt::Calendar`, which is optimized for runtime efficiency,
52/// `bdlt::PackedCalendar` is designed to minimize the amount of in-process
53/// memory required to represent that information. For example, a packed
54/// calendar storing 250 holidays and holiday codes can consume as little as
55/// approximately 0.75K bytes (e.g., 2 bytes per holiday plus 1 byte per
56/// holiday code) to as much as approximately 3K bytes (e.g., 8 bytes per
57/// holiday plus 4 bytes per holiday code) depending upon the data of the
58/// calendar. For typical calendars having a range of 40 years and 10 holidays
59/// per year, the expected size of the packed calendar is about half that of a
60/// similar implementation using a non-packed structure.
61///
62/// Default-constructed calendars are empty, and have an empty valid range.
63/// Calendars can also be constructed with an initial (non-empty) valid range,
64/// implying that all dates within that range are business days. The
65/// `setValidRange` and `addDay` methods modify the valid range of a calendar,
66/// and a suite of "add" methods can be used to populate a calendar with
67/// weekend days and holidays.
68///
69/// The `addHolidayCode` method associates an integer "holiday code" with a
70/// specific date, and can be called repeatedly with different integers and the
71/// same date to build up a set of holiday codes for that date. Note that
72/// holiday codes are unique integers that, from the perspective of the
73/// calendar, have no particular meaning. Typically, the user will choose
74/// holiday code values that are indices into an auxiliary collection (such as a
75/// `bsl::vector<bsl::string>`) to identify holiday names for end-user display.
76///
77/// Once a calendar is populated, a rich set of accessor methods can be used to
78/// determine, e.g., if a given date is a business day, or the number of
79/// non-business days within some subrange of the calendar. The holidays
80/// within a calendar can be obtained in increasing (chronological) order using
81/// an iterator identified by the nested `HolidayConstIterator` `typedef`. The
82/// set of holiday codes associated with an arbitrary date in a
83/// `bdlt::PackedCalendar` (or the current holiday referred to by a
84/// `HolidayConstIterator`) can be obtained in increasing (numerical) order
85/// using an iterator identified by the nested `HolidayCodeConstIterator`
86/// `typedef` (see below).
87///
88/// Calendars are value-semantic objects, and, as such, necessarily support all
89/// of the standard value-semantic operations, such as default construction,
90/// copy construction and copy assignment, equality comparison, and
91/// externalization (BDEX streaming, in particular). Calendars also support
92/// the notions of both union and intersection merging operations, whereby a
93/// calendar can change its value to contain the union or intersection of its
94/// own contained weekend days, holidays, and holiday codes with those of
95/// another calendar object. Such merging operations will, in general, also
96/// alter the valid range of the resulting calendar. Note that merged
97/// calendars can be significantly more efficient for certain repeated
98/// "is-common-business-day" determinations among two or more calendars.
99///
100/// ## Weekend Days and Weekend-Days Transitions {#bdlt_packedcalendar-weekend-days-and-weekend-days-transitions}
101///
102///
103/// A calendar maintains a set of dates considered to be weekend days.
104/// Typically, a calendar's weekend days fall on the same days of the week for
105/// the entire range of a calendar. For example, the weekend for United States
106/// has consisted of Saturday and Sunday since the year 1940. The
107/// `addWeekendDay` and `addWeekendDays` methods can be used to specify the
108/// weekend days for these calendars.
109///
110/// However, sometimes a calendar's weekend days changes over time. For
111/// example, Bangladesh's weekend consisted of Friday until June 1, 1997 when
112/// Bangladesh changed its weekends to contain both Friday and Saturday. Later,
113/// on October 1, 2001, Bangladesh reverted to a weekend of only Friday, until
114/// on September 9, 2009, Bangladesh again changed its weekends to include both
115/// Friday and Saturday.
116///
117/// To optimize for space allocation while supporting both consistent and
118/// changing weekend days, a calendar represents weekend information using a
119/// sequence of "weekend-days transitions", each of which comprises a date and a
120/// set of days of the week considered to be the weekend on and after that
121/// date. To represent the weekend days of Bangladesh, a calendar can use a
122/// sequence of four weekend-days transitions: (1) a transition on January 1,
123/// 0001 having a weekend day set containing only Friday, (2) a transition at
124/// June 1, 1997 having a weekend day set containing Friday and Saturday, (3) a
125/// transition at October 1, 2001 having a weekend day set containing only
126/// Friday, and (4) a transition at September 9, 2009 having a weekend day set
127/// containing Friday and Saturday. To represent the weekend days of the United
128/// States, a calendar having a range after 1940 can use a single weekend-days
129/// transition on January 1, 0001 containing Saturday and Sunday.
130///
131/// On construction, a calendar does not contain any weekend-days transitions.
132/// The `addWeekendDaysTransition` method adds a new weekend-days transition or
133/// replaces an existing weekend-days transition. The `addWeekendDay` and
134/// `addWeekendDays` methods create a weekend-days transition at January 1,
135/// 0001, if one doesn't already exist, and update the set of weekend days for
136/// that transition. `addWeekendDay` and `addWeekendDays` should only be used
137/// for calendars having a consistent set of weekend days throughout their
138/// entire range. The use of `addWeekendDay` and `addWeekendDays` is intended
139/// to be *mutually* *exclusive* to the use of `addWeekendDaysTransition`. As
140/// such, the behavior of using these two methods together with
141/// `addWeekendDaysTransition` is undefined.
142///
143/// ## Nested Iterators {#bdlt_packedcalendar-nested-iterators}
144///
145///
146/// Also provided are several STL-style `const` bidirectional iterators
147/// accessible as nested `typedef`s. `HolidayConstIterator`,
148/// `HolidayCodeConstIterator`, `WeekendDaysTransitionConstIterator`, and
149/// `BusinessDayConstIterator`, respectively, iterate over a chronologically
150/// ordered sequence of holidays, a numerically ordered sequence of holiday
151/// codes, a sequence of chronologically ordered weekend-days transitions, and a
152/// sequence of chronologically ordered business days. Reverse iterators are
153/// also provided for each of these (forward) iterators. As a general rule,
154/// calling a `const` method will not invalidate any iterators, and calling a
155/// non-`const` method might invalidate all of them; it is, however, guaranteed
156/// that attempting to add *duplicate* holidays or holiday codes will have no
157/// effect, and therefore will not invalidate any iterators. It is also
158/// guaranteed that adding a new code for an existing holiday will not
159/// invalidate any `HolidayConstIterator` objects.
160///
161/// Note that these iterators do *not* meet the requirements for a
162/// `bsl::forward_iterator` and should not be used in standard algorithms (e.g.,
163/// `bsl::lower_bound`).
164///
165/// ## Iterator Invalidation {#bdlt_packedcalendar-iterator-invalidation}
166///
167///
168/// The modification of a `bdlt::PackedCalendar` will invalidate iterators
169/// referring to the calendar. The following table shows the relationship
170/// between a calendar manipulator and the types of iterators it will
171/// invalidate if the invocation of the manipulator modified the calendar (e.g.,
172/// using `addHoliday` with a date that is not currently a holiday in the
173/// calendar):
174/// @code
175/// Manipulator Invalidates
176/// -------------------------- --------------------
177/// `operator=` H HC WDT BD
178/// `addHoliday` H HC BD
179/// `addHolidayCode` HC
180/// `addHolidayCodeIfInRange` HC
181/// `addHolidayIfInRange` H HC BD
182/// `addWeekendDay` WDT BD
183/// `addWeekendDays` WDT BD
184/// `addWeekendDaysTransition` WDT BD
185/// `intersectBusinessDays` H HC WDT BD
186/// `intersectNonBusinessDays` H HC WDT BD
187/// `removeAll` H HC WDT BD
188/// `removeHoliday` H HC BD
189/// `removeHolidayCode` HC
190/// `setValidRange` H HC BD
191/// `unionBusinessDays` H HC WDT BD
192/// `unionNonBusinessDays` H HC WDT BD
193///
194/// where "H" represents the holiday iterators (`HolidayConstIterator` and
195/// `HolidayConstReverseIterator`), "HC" represents the holiday code iterators
196/// (`HolidayCodeConstIterator` and `HolidayCodeConstReverseIterator`), "WDT"
197/// represents the weekend-days transition iterators
198/// (`WeekendDaysTransitionConstIterator` and
199/// `WeekendDaysTransitionConstReverseIterator`), and "BD" represents the
200/// business day iterators (`BusinessDayConstIterator` and
201/// `BusinessDayConstReverseIterator`).
202/// @endcode
203///
204/// ## Performance and Exception-Safety Guarantees {#bdlt_packedcalendar-performance-and-exception-safety-guarantees}
205///
206///
207/// The asymptotic worst-case performance of representative operations is
208/// characterized using big-O notation, `O[f(N,M,W,V)]`. `N` and `M` each refer
209/// to the combined number (`H + C`) of holidays `H` (i.e., method
210/// `numHolidays`) and holiday codes `C` (i.e., `numHolidayCodesTotal`) in the
211/// respective packed calendars. `W` and `V` each refer to the (likely small)
212/// number of weekend-days transitions in the respective packed calendars. For
213/// clarity, the methods have abbreviated arguments: `b`, `e`, and `d` are
214/// dates, `c` is a holiday code, `u` is a weekday, and `w` is a set of
215/// weekdays. Here, *Best* *Case* complexity, denoted by `B[f(N)]`, is loosely
216/// defined (for manipulators) as the worst-case cost, provided that (1) no
217/// additional internal capacity is required, (2) the start of the valid range
218/// does not change, and (3) that if a holiday (or holiday code) is being added,
219/// it is being appended *to* *the* *end* of the current sequence (of the latest
220/// holiday).
221/// @code
222/// Worst Best Exception-Safety
223/// Operation Case Case Guarantee
224/// --------- ----- ---- ----------------
225/// DEFAULT CTOR O[1] No-Throw
226/// COPY CTOR(N) O[N] Exception-Safe
227/// N.DTOR() O[1] No-Throw
228///
229/// N.OP=(M) O[M] Basic <*>
230///
231/// N.reserveCapacity(H, C) O[N] Strong <*>
232///
233/// N.setValidRange(b, e) O[N] O[1] Basic <*>
234/// N.addDay(d) O[N] O[1] Basic <*>
235/// N.addHoliday(d) O[N] O[1] Basic <*>
236/// N.addHolidayCode(d,c) O[N] O[1] Basic <*>
237///
238/// N.addWeekendDay(u) O[1] No-Throw
239/// N.addWeekendDaysTransition(d,w) O[W] Basic <*>
240///
241/// N.intersectBusinessDays(M) O[N+M+W+V] Basic <*>
242/// N.intersectNonBusinessDays(M) O[N+M+W+V] Basic <*>
243/// N.unionBusinessDays(M) O[N+M+W+V] Basic <*>
244/// N.unionNonBusinessDays(M) O[N+M+W+V] Basic <*>
245///
246/// N.removeHoliday(d) O[N] No-Throw
247/// N.removeHolidayCode(d, c) O[N] No-Throw
248/// N.removeAll(); O[1] No-Throw
249///
250/// N.swap(M) O[1] No-Throw
251///
252/// N.firstDate() O[1] No-Throw
253/// N.lastDate() O[1] No-Throw
254/// N.length() O[1] No-Throw
255///
256/// N.numHolidays() O[1] No-Throw
257///
258/// N.numHolidayCodesTotal() O[1] No-Throw
259/// N.numWeekendDaysInRange() O[1] No-Throw
260///
261/// N.isInRange(d); O[1] No-Throw
262/// N.isWeekendDay(w); O[1] No-Throw
263/// N.isWeekendDay(d) O[log(W)] No-Throw
264///
265/// N.isHoliday(d); O[log(N)] No_Throw
266/// N.isBusinessDay(d); O[log(N)] No_Throw
267/// N.isNonBusinessDay(d); O[log(N)] No_Throw
268///
269/// N.numHolidayCodes(d) O[log(N)] No-Throw
270///
271/// N.numBusinessDays() O[N] No-Throw
272/// N.numNonBusinessDays() O[N] No-Throw
273///
274/// other 'const' methods O[1] .. O[N] No-Throw
275///
276///
277/// OP==(N,M) O[min(N,M)+min(W+V) No-Throw
278/// OP!=(N,M) O[min(N,M)+min(W+V) No-Throw
279///
280/// <*> No-Throw guarantee when capacity is sufficient.
281/// @endcode
282/// Note that *all* of the non-creator methods of `bdlt::PackedCalendar` provide
283/// the *No-Throw* guarantee whenever sufficient capacity is already available.
284/// Also note that these are largely the same as `bdlt::Calendar` *except* that
285/// the accessors `isBusinessDay` and `isNonBusinessDay` are logarithmic in the
286/// number of holidays in `bdlt::PackedCalendar`.
287///
288/// ## Usage {#bdlt_packedcalendar-usage}
289///
290///
291/// The two subsections below illustrate various aspects of populating and using
292/// packed calendars.
293///
294/// ### Example 1: Populating Packed Calendars {#bdlt_packedcalendar-example-1-populating-packed-calendars}
295///
296///
297/// Packed calendars will typically be populated from a database or flat file.
298/// The user should employ an appropriate population mechanism that provides
299/// the desired holiday dates and associated holiday codes within some desired
300/// range. For example, suppose we have created the following flat-file format
301/// that encodes calendar information, including holidays and holiday codes (we
302/// assume, for the simplicity of this example, that "Weekend Days" (i.e.,
303/// recurring non-business days) are always just Saturdays and Sundays):
304/// @code
305/// // HOLIDAY DATE HOLIDAY CODES
306/// // ------------ -------------
307/// // Year Mon Day # Codes Comments, separated by Semicolons (;)
308/// // ---- --- --- --- --------- -------------------------------------
309/// 2010 1 18 1 57 ;Martin Luther King, Jr. Day
310/// 2010 2 15 1 51 ;Presidents Day
311/// 2010 4 2 2 9 105 ;Easter Sunday (Observed); Good Friday
312/// 2010 5 31 1 16 ;Memorial Day
313/// 2010 7 5 1 28 ;Independence Day (Observed)
314/// 2010 9 6 1 44 ;Labor Day
315/// 2010 10 11 1 19 ;Columbus Day
316/// 2010 11 2 0 ;Election Day
317/// 2010 11 25 1 14 ;Thanksgiving Day
318/// 2010 12 25 1 4 ;Christmas Day (Observed)
319/// 2010 12 31 1 22 ;New Year's Day (Observed)
320/// @endcode
321/// Let's now create a couple of primitive helper functions to extract holiday
322/// and holiday-code counts from a given input stream.
323///
324/// First, we'll create a helper function to get a holiday record:
325/// @code
326/// /// Load into the specified `holiday` the date of the next holiday, and
327/// /// into the specified `numCodes` the associated number of holiday codes
328/// /// for the holiday read from the specified `input` stream. Return 0 on
329/// /// success, and a non-zero value (with no effect on `*holiday` and
330/// /// `*numCodes`) otherwise.
331/// int getNextHoliday(bsl::istream& input, bdlt::Date *holiday, int *numCodes)
332/// {
333/// enum { SUCCESS = 0, FAILURE = 1 };
334///
335/// int year, month, day, codes;
336///
337/// if (input.good()) {
338/// input >> year;
339/// }
340/// if (input.good()) {
341/// input >> month;
342/// }
343/// if (input.good()) {
344/// input >> day;
345/// }
346/// if (input.good()) {
347/// input >> codes;
348/// }
349///
350/// if (input.good()
351/// && bdlt::Date::isValidYearMonthDay(year, month, day)) {
352/// *holiday = bdlt::Date(year, month, day);
353/// *numCodes = codes;
354/// return SUCCESS; // RETURN
355/// }
356///
357/// return FAILURE; // RETURN
358/// }
359/// @endcode
360/// Then, we'll write a function that gets us an integer holiday code, or
361/// invalidates the stream if it cannot (note that negative holiday codes are
362/// not supported by this function, but negative holiday codes *are* supported
363/// by `bdlt::PackedCalendar`):
364/// @code
365/// /// Load, into the specified `result`, the value read from the specified
366/// /// `input` stream. If the next token is not an integer, invalidate the
367/// /// stream with no effect on `result`.
368/// void getNextHolidayCode(bsl::istream& input, int *result)
369/// {
370/// int holidayCode;
371///
372/// if (input.good()) {
373/// input >> holidayCode;
374/// }
375///
376/// if (input.good()) {
377/// *result = holidayCode;
378/// }
379/// }
380/// @endcode
381/// Now, with these helper functions, it is a simple matter to write a calendar
382/// loader function, `load`, that populates a given calendar with data in this
383/// "proprietary" format:
384/// @code
385/// /// Populate the specified `calendar` with holidays and corresponding
386/// /// codes read from the specified `input` stream in our "proprietary"
387/// /// format (see above). On success, `input` will be empty, but valid;
388/// /// otherwise `input` will be invalid.
389/// void load(bsl::istream& input, bdlt::PackedCalendar *calendar)
390/// {
391/// bdlt::Date holiday;
392/// int numCodes;
393///
394/// while (0 == getNextHoliday(input, &holiday, &numCodes)) {
395/// calendar->addHoliday(holiday); // add date
396/// for (int i = 0; i < numCodes; ++i) {
397/// int holidayCode = 0;
398/// getNextHolidayCode(input, &holidayCode);
399/// if (input.good()) {
400/// // add codes
401///
402/// calendar->addHolidayCode(holiday, holidayCode);
403/// }
404/// }
405/// input.ignore(256, '\n'); // skip comments
406/// }
407/// }
408/// @endcode
409/// Finally, we load a `bdlt::PackedCalendar` and verify some values from the
410/// calendar.
411/// @code
412/// bsl::stringstream stream;
413/// {
414/// stream << "2010 9 6 1 44 ;Labor Day\n"
415/// << "2010 10 11 1 19 ;Columbus Day\n"
416/// << "2010 11 2 0 ;Election Day\n"
417/// << "2010 11 25 1 14 ;Thanksgiving Day\n";
418/// }
419///
420/// bdlt::PackedCalendar calendar;
421/// load(stream, &calendar);
422///
423/// assert(bdlt::Date(2010, 9, 6) == calendar.firstDate());
424/// assert(bdlt::Date(2010, 11, 25) == calendar.lastDate());
425/// assert(true == calendar.isBusinessDay(bdlt::Date(2010, 10, 12)));
426/// assert(false == calendar.isBusinessDay(bdlt::Date(2010, 11, 2)));
427/// @endcode
428/// Note that different formats can easily be accommodated, while still using
429/// the same basic population strategy. Also note that it may be substantially
430/// more efficient to populate calendars in increasing date order, compared to
431/// either reverse or random order.
432///
433/// ### Example 2: Using Packed Calendars {#bdlt_packedcalendar-example-2-using-packed-calendars}
434///
435///
436/// Higher-level clients (e.g., a GUI) may need to extract the holiday codes
437/// for a particular date, use them to look up their corresponding string names
438/// in a separate repository (e.g., a vector of strings), and to display these
439/// names to end users.
440///
441/// First, let's create a function that prints the names of holidays for a
442/// given date:
443/// @code
444/// /// Write, to the specified `output` stream, the elements in the
445/// /// specified `holidayNames` associated, via holiday codes in the
446/// /// specified `calendar`, to the specified `date`. Each holiday name
447/// /// emitted is followed by a newline (`\n`). The behavior is undefined
448/// /// unless `date` is within the valid range of `calendar`.
449/// void
450/// printHolidayNamesForGivenDate(bsl::ostream& output,
451/// const bdlt::PackedCalendar& calendar,
452/// const bdlt::Date& date,
453/// const bsl::vector<bsl::string>& holidayNames)
454/// {
455/// for (bdlt::PackedCalendar::HolidayCodeConstIterator
456/// it = calendar.beginHolidayCodes(date);
457/// it != calendar.endHolidayCodes(date);
458/// ++it) {
459/// output << holidayNames[*it] << bsl::endl;
460/// }
461/// }
462/// @endcode
463/// Then, since we can write the names of holidays for a given date, let's
464/// write a function that can write out all of the names associated with each
465/// holiday in the calendar:
466/// @code
467/// /// Write, to the specified `output` stream, each date associated with
468/// /// a holiday in the specified `calendar` followed by any elements in
469/// /// the specified `holidayNames` (associated via holiday codes in
470/// /// `calendar`) corresponding to that date. Each date emitted is
471/// /// preceded and followed by a newline (`\n`). Each holiday name
472/// /// emitted is followed by a newline (`\n`).
473/// void
474/// printHolidayDatesAndNames(bsl::ostream& output,
475/// const bdlt::PackedCalendar& calendar,
476/// const bsl::vector<bsl::string>& holidayNames)
477/// {
478/// for (bdlt::PackedCalendar::HolidayConstIterator
479/// it = calendar.beginHolidays();
480/// it != calendar.endHolidays(); ++it) {
481/// output << '\n' << *it << '\n';
482/// printHolidayNamesForGivenDate(output,
483/// calendar,
484/// *it,
485/// holidayNames);
486/// }
487/// }
488/// @endcode
489/// Next, we populate the `holidayNames` vector:
490/// @code
491/// bsl::vector<bsl::string> holidayNames;
492/// {
493/// holidayNames.resize(45);
494///
495/// holidayNames[44] = "Labor Day"; // holiday code 44 is for
496/// // Labor Day
497///
498/// holidayNames[14] = "Thanksgiving Day"; // holiday code 14 is for
499/// // Thanksgiving Day
500/// }
501/// @endcode
502/// Now, using the `calendar` populated in the previous example, we print the
503/// holiday information to a new `bsl::stringstream`:
504/// @code
505/// bsl::stringstream printStream;
506///
507/// printHolidayDatesAndNames(printStream, calendar, holidayNames);
508/// @endcode
509/// Finally, we verify the output:
510/// @code
511/// assert(printStream.str() == "\n06SEP2010\nLabor Day\n\n11OCT2010\n\n\n"
512/// "02NOV2010\n\n25NOV2010\nThanksgiving Day\n");
513/// @endcode
514/// @}
515/** @} */
516/** @} */
517
518/** @addtogroup bdl
519 * @{
520 */
521/** @addtogroup bdlt
522 * @{
523 */
524/** @addtogroup bdlt_packedcalendar
525 * @{
526 */
527
528#include <bdlscm_version.h>
529
531#include <bdlt_date.h>
532#include <bdlt_dayofweek.h>
533#include <bdlt_dayofweekset.h>
534
535#include <bdlc_packedintarray.h>
537
538#include <bslalg_swaputil.h>
539
540#include <bslh_hash.h>
541
542#include <bslma_allocator.h>
544
546
547#include <bsls_assert.h>
548#include <bsls_preconditions.h>
549#include <bsls_review.h>
550
551#include <bsl_cstddef.h>
552#include <bsl_iosfwd.h>
553#include <bsl_iterator.h>
554#include <bsl_utility.h> // 'bsl::pair'
555#include <bsl_vector.h>
556
557#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
558#include <bslalg_typetraits.h>
559
560#include <bsl_algorithm.h>
561#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
562
563
564namespace bdlt {
565
566class PackedCalendar_BusinessDayConstIterator;
567class PackedCalendar_HolidayCodeConstIterator;
568class PackedCalendar_HolidayConstIterator;
569
570 // ====================
571 // class PackedCalendar
572 // ====================
573
574/// This class implements a space-efficient, value-semantic repository of
575/// weekend and holiday information over a *valid* *range* of dates. This
576/// valid range, `[firstDate() .. lastDate()]`, spans the first and last
577/// dates of a calendar's accessible contents. A calendar can be
578/// "populated" with weekend and holiday information via a suite of "add"
579/// methods. Any subset of days of the week may be specified as weekend
580/// (i.e., recurring non-business) days starting from a specified date by
581/// adding a weekend-days transition; holidays within the valid range are
582/// specified individually. When adding a holiday, an arbitrary integer
583/// "holiday code" may be associated with that date. Additional holiday
584/// codes for that date may subsequently be added. Both the holidays and
585/// the set of unique holiday codes associated with each holiday date are maintained (internally) in order of increasing value.
586///
587/// \note Note that the
588/// behavior of requesting *any* calendar information for a supplied date
589/// whose value is outside the current *valid* *range* for that calendar
590/// (unless otherwise noted, e.g., `isWeekendDay`) is undefined.
591///
592/// See @ref bdlt_packedcalendar
594
595 private:
596 // PRIVATE TYPES
597 typedef bsl::pair<Date, DayOfWeekSet> WeekendDaysTransitionPrivate;
598
602
604 WeekendDaysTransitionSequence;
605
606 /// This `struct` provides a comparator predicate for the type
607 /// `WeekendDaysTransition` to enable the use of standard algorithms
608 /// (such as `bsl::lower_bound`) on ranges of objects of that type.
609 ///
610 /// See @ref bdlt_packedcalendar
611 struct WeekendDaysTransitionLess {
612
613 // ACCESSORS
614
615 /// Return `true` if the value of the specified `lhs` is less than
616 /// (ordered before) the value of the specified `rhs`, and `false`
617 /// otherwise. The value of `lhs` is less than the value of `rhs`
618 /// if the date represented by the data member `first` of `lhs` is
619 /// earlier than the date represented by the data member `first` of
620 /// `rhs`.
621 bool operator()(const WeekendDaysTransitionPrivate& lhs,
622 const WeekendDaysTransitionPrivate& rhs) const
623 {
624 return lhs.first < rhs.first;
625 }
626 };
627
628 public:
629 // TYPES
630 typedef WeekendDaysTransitionPrivate WeekendDaysTransition;
631
633
635
637
640
643
646
647 typedef WeekendDaysTransitionSequence::const_iterator
649
650 typedef
651 bsl::reverse_iterator<WeekendDaysTransitionSequence::const_iterator>
653
654 private:
655 // DATA
656 Date d_firstDate; // first valid date of calendar or
657 // 9999/12/31 if this calendar is
658 // empty
659
660 Date d_lastDate; // last valid date of calendar or
661 // 0001/01/01 if this calendar is
662 // empty
663
665 d_weekendDaysTransitions;
666 // chronological list of weekend-
667 // days transitions
668
669 bdlc::PackedIntArray<int> d_holidayOffsets;
670 // ordered list of all holidays in
671 // this calendar stored as offsets
672 // from 'd_firstDate'
673
674 bdlc::PackedIntArray<int> d_holidayCodesIndex;
675 // parallel to 'd_holidayOffsets',
676 // this is a list of indices into
677 // 'd_holidayCodes'; note that the
678 // end of each sequence can be
679 // determined using the value of
680 // the next entry in this array if
681 // it exists, or else the length
682 // of 'd_holidayCodes' itself
683
684 bdlc::PackedIntArray<int> d_holidayCodes;
685 // sequences of holiday codes,
686 // each partitioned into an
687 // ordered "chunk" of codes per
688 // holiday in 'd_holidayOffsets';
689 // chunks are stored in the same
690 // order as in 'd_holidayOffsets'
691
692 bslma::Allocator *d_allocator_p;
693 // memory allocator (held, not
694 // owned)
695
696 // FRIENDS
698
699 friend bool operator==(const PackedCalendar&, const PackedCalendar&);
700 friend bool operator!=(const PackedCalendar&, const PackedCalendar&);
701 template <class HASHALG>
702 friend void hashAppend(HASHALG& hashAlg, const PackedCalendar&);
703
704 private:
705 // PRIVATE CLASS METHODS
706
707 /// Append, onto the specified `resHolidayOffsets`,
708 /// `resHolidayCodesIndex`, and `resHolidayCodes`, the intersection of
709 /// the holidays from the specified `lhs` and `rhs` calendars
710 /// restricted to the date range of the specified `firstDate` and `lastDate`.
711 ///
712 /// \pre The behavior is undefined unless
713 /// `firstDate <= lastDate`.
714 static void intersectHolidays(
715 bdlc::PackedIntArray<int> *resHolidayOffsets,
716 bdlc::PackedIntArray<int> *resHolidayCodesIndex,
717 bdlc::PackedIntArray<int> *resHolidayCodes,
718 const PackedCalendar& lhs,
719 const PackedCalendar& rhs,
720 const bdlt::Date firstDate,
721 const bdlt::Date lastDate);
722
723 /// Append, onto the specified `resHolidayOffsets`,
724 /// `resHolidayCodesIndex`, and `resHolidayCodes`, the union of the
725 /// holidays from the specified `lhs` and `rhs` calendars restricted to
726 /// the date range of the specified `firstDate` and `lastDate`.
727 ///
728 /// \pre The behavior is undefined unless `firstDate <= lastDate`.
729 static void unionHolidays(bdlc::PackedIntArray<int> *resHolidayOffsets,
730 bdlc::PackedIntArray<int> *resHolidayCodesIndex,
731 bdlc::PackedIntArray<int> *resHolidayCodes,
732 const PackedCalendar& lhs,
733 const PackedCalendar& rhs,
734 const bdlt::Date firstDate,
735 const bdlt::Date lastDate);
736
737 // PRIVATE MANIPULATORS
738
739 /// Add the specified `offset` as a holiday offset in this calendar. If
740 /// the date represented by `offset` is already a holiday, this method
741 /// has no effect. Return the index of `d_holidayOffsets` where `offset` is stored.
742 ///
743 /// \pre The behavior is undefined unless `0 <= offset`
744 /// and the `offset` represents a date within the valid range of the
745 /// calendar.
746 int addHolidayImp(int offset);
747
748 // PRIVATE ACCESSORS
749
750 /// Return an iterator that refers to the first non-modifiable holiday
751 /// code for the holiday referenced by the specified `iter`. If there
752 /// are no holiday codes associated with the date referenced by `iter`,
753 /// the returned iterator has the same value as that returned by `endHolidayCodes(iter)`.
754 ///
755 /// \pre The behavior is undefined unless `iter`
756 /// refers to a valid holiday of this calendar.
757 CodesConstIterator beginHolidayCodes(
758 const OffsetsConstIterator& iter) const;
759
760 /// Return an iterator that indicates the element one past the last
761 /// holiday code associated with the date referenced by the specified `iter`.
762 ///
763 /// \pre The behavior is undefined unless `iter` references a valid
764 /// holiday in this calendar.
765 CodesConstIterator endHolidayCodes(const OffsetsConstIterator& iter) const;
766
767 public:
768 // CLASS METHODS
769
770 // Aspects
771
772 /// Return the maximum valid BDEX format version, as indicated by the
773 /// specified `versionSelector`, to be passed to the `bdexStreamOut` method.
774 ///
775 /// \note Note that it is highly recommended that `versionSelector`
776 /// be formatted as "YYYYMMDD", a date representation. Also note that
777 /// `versionSelector` should be a *compile*-time-chosen value that
778 /// selects a format version supported by both externalizer and
779 /// unexternalizer. See the `bslx` package-level documentation for more
780 /// information on BDEX streaming of value-semantic types and
781 /// containers.
782 static int maxSupportedBdexVersion(int versionSelector);
783
784 // CREATORS
785
786 /// Create an empty calendar, i.e., a calendar having an empty valid
787 /// range. Optionally specify a `basicAllocator` used to supply memory.
788 /// If `basicAllocator` is 0, the currently installed default allocator
789 /// is used.
790 explicit PackedCalendar(bslma::Allocator *basicAllocator = 0);
791
792 /// Create a calendar having a valid range from the specified
793 /// `firstDate` through the specified `lastDate`. Optionally specify a
794 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
795 /// the currently installed default allocator is used.
796 ///
797 /// \pre The behavior is undefined unless `firstDate <= lastDate`.
799 const Date& lastDate,
800 bslma::Allocator *basicAllocator = 0);
801
802 /// Create a calendar having the value of the specified `original`
803 /// calendar. Optionally specify a `basicAllocator` used to supply
804 /// memory. If `basicAllocator` is 0, the currently installed default
805 /// allocator is used.
807 bslma::Allocator *basicAllocator = 0);
808
809 /// Destroy this object.
811
812 // MANIPULATORS
813
814 /// Assign to this calendar the value of the specified `rhs` calendar,
815 /// and return a reference providing modifiable access to this calendar.
816 /// See {Iterator Invalidation} for information regarding which
817 /// iterators are affected by the use of this method.
819
820 /// Extend the valid range (if necessary) of this calendar to include
821 /// the specified `date` value.
822 void addDay(const Date& date);
823
824 /// Mark the specified `date` as a holiday (i.e., a non-business day)
825 /// in this calendar. Extend the valid range of this calendar if
826 /// necessary. If `date` is already marked as a holiday, this method
827 /// has no effect. See {Iterator Invalidation} for information
828 /// regarding which iterators are affected by the use of this method.
829 void addHoliday(const Date& date);
830
831 /// Mark the specified `date` as a holiday (i.e., a non-business day) in
832 /// this calendar and add the specified `holidayCode` (if not already
833 /// present) to the ordered set of codes associated with `date`.
834 /// Extend the valid range of this calendar if necessary. If
835 /// `holidayCode` is already a code for `date`, this method has no
836 /// effect. See {Iterator Invalidation} for information regarding
837 /// which iterators are affected by the use of this method.
838 void addHolidayCode(const Date& date, int holidayCode);
839
840 /// Mark the specified `date` as a holiday (i.e., a non-business day)
841 /// in this calendar and add the specified `holidayCode` (if not
842 /// already present) to the set of codes associated with `date`, if
843 /// `date` is within the valid range of this calendar. Return 0 if
844 /// `date` is in range, and a non-zero value otherwise. If
845 /// `holidayCode` is already a code for `date`, or if `date` is not in
846 /// the valid range, this method has no effect. See
847 /// {Iterator Invalidation} for information regarding which iterators are affected by the use of this method.
848 ///
849 /// \note Note that this method may
850 /// be called repeatedly with the same value for `date` to build up a
851 /// set of holiday codes for that date.
852 int addHolidayCodeIfInRange(const Date& date, int holidayCode);
853
854 /// Mark the specified `date` as a holiday (i.e., a non-business day) in
855 /// this calendar if `date` is within the valid range. Return 0 if
856 /// `date` is in range, and a non-zero value otherwise. This method has
857 /// no effect if `date` is already marked as a holiday or is not in the
858 /// valid range. See {Iterator Invalidation} for information regarding
859 /// which iterators are affected by the use of this method.
860 int addHolidayIfInRange(const Date& date);
861
862 /// Add the specified `weekendDay` to the set of weekend days associated
863 /// with the weekend-days transition at January 1, 0001 maintained by
864 /// this calendar. Create a transition at January 1, 0001 if one does
865 /// not exist. See {Iterator Invalidation} for information regarding
866 /// which iterators are affected by the use of this method.
867 ///
868 /// \pre The behavior is undefined unless no weekend-days transitions were added
869 /// to this calendar via the `addWeekendDaysTransition` method.
871
872 /// Add the specified `weekendDays` to the set of weekend days
873 /// associated with the weekend-days transition at January 1, 0001
874 /// maintained by this calendar. Create a transition at January 1, 0001
875 /// if one does not exist. See {Iterator Invalidation} for information
876 /// regarding which iterators are affected by the use of this method.
877 ///
878 /// \pre The behavior is undefined unless no weekend-days transitions were
879 /// added to this calendar via the `addWeekendDaysTransition` method.
880 void addWeekendDays(const DayOfWeekSet& weekendDays);
881
882 /// Add to this calendar a weekend-days transition on the specified
883 /// `startDate` having the specified `weekendDays` set. If a
884 /// weekend-days transition already exists on `startDate`, replace the
885 /// set of weekend days of that transition with `weekendDays`. See
886 /// {Iterator Invalidation} for information regarding which iterators are affected by the use of this method.
887 ///
888 /// \note Note that this method does
889 /// not extend the valid range of the calendar.
890 void addWeekendDaysTransition(const Date& startDate,
891 const DayOfWeekSet& weekendDays);
892
893 /// Merge the specified `other` calendar into this calendar such that
894 /// the valid range of this calendar becomes the *intersection* of the
895 /// two calendars' ranges, and the weekend days and holidays for this
896 /// calendar become the union of those (non-business) days from the two
897 /// calendars -- i.e., the valid business days of this calendar become
898 /// the intersection of those of the two original calendar values over
899 /// the *intersection* of their ranges. For each holiday that remains,
900 /// the resulting holiday codes in this calendar will be the union of
901 /// the corresponding original holiday codes. See
902 /// {Iterator Invalidation} for information regarding which iterators
903 /// are affected by the use of this method.
905
906 /// Merge the specified `other` calendar into this calendar such that
907 /// the valid range of this calendar becomes the *intersection* of the
908 /// two calendars' ranges, the weekend days for this calendar become the
909 /// intersection of those days from the two calendars, and the holidays
910 /// for this calendar become the set of days that are a holiday in one
911 /// of the calendars and a non-business day in the other calendar --
912 /// i.e., the valid business days of this calendar become the union of
913 /// those of the two original calendars over the *intersection* of their
914 /// ranges. For each holiday that remains, the resulting holiday codes
915 /// in this calendar will be the union of the corresponding original
916 /// holiday codes. See {Iterator Invalidation} for information
917 /// regarding which iterators are affected by the use of this method.
919
920 /// Remove all information from this calendar, leaving it with its
921 /// default constructed "empty" value. See {Iterator Invalidation} for
922 /// information regarding which iterators are affected by the use of
923 /// this method.
924 void removeAll();
925
926 /// Remove from this calendar the holiday having the specified `date` if
927 /// such a holiday exists. This operation has no effect if `date` is
928 /// not a holiday in this calendar. See {Iterator Invalidation} for
929 /// information regarding which iterators are affected by the use of this method.
930 ///
931 /// \note Note that this method is defined for all `date`
932 /// values, not just those that fall within the valid range, and may be
933 /// invoked even on an empty calendar (i.e., having `0 == length()`).
934 void removeHoliday(const Date& date);
935
936 /// Remove from this calendar the specified `holidayCode` for the
937 /// holiday having the specified `date` if such a holiday having
938 /// `holidayCode` exists. This operation has no effect if `date` is not
939 /// a holiday in this calendar, or if the holiday at `date` does not
940 /// have `holidayCode` associated with it. See {Iterator Invalidation}
941 /// for information regarding which iterators are affected by the use of this method.
942 ///
943 /// \note Note that this method is defined for all `date`
944 /// values, not just those that fall within the valid range, and may be
945 /// invoked even on an empty calendar (i.e., having `0 == length()`).
946 void removeHolidayCode(const Date& date, int holidayCode);
947
948 /// Reserve enough space to store at least the specified `numHolidays`
949 /// within this calendar. This method has no effect if
950 /// `numHolidays <= numHolidays()`.
952
953 /// Reserve enough space to store at least the specified
954 /// `numHolidayCodes` within this calendar assuming no additional
955 /// holidays are added to this calendar. This method has no effect if
956 /// `numHolidayCodes <= numHolidayCodesTotal()`.
958
959 /// Set the range of this calendar using the specified `firstDate` and
960 /// `lastDate` as, respectively, the first date and the last date of the
961 /// calendar. Any holiday that is outside the new range and its holiday
962 /// codes are removed. See {Iterator Invalidation} for information
963 /// regarding which iterators are affected by the use of this method.
964 ///
965 /// \pre The behavior is undefined unless `firstDate <= lastDate`.
967
968 /// Merge the specified `other` calendar into this calendar such that
969 /// the valid range of this calendar becomes the *union* of the two
970 /// calendars' ranges (or the minimal continuous range spanning the two
971 /// ranges, if the ranges are non-overlapping), the weekend days for
972 /// this calendar become the intersection of those days from the two
973 /// calendars, and the holidays for this calendar become the set of days
974 /// that are a holiday in one of the calendars and a non-business day in
975 /// the other calendar -- i.e., the valid business days of this calendar
976 /// become the union of those of the two original calendar values. For
977 /// each holiday that remains, the resulting holiday codes in this
978 /// calendar will be the union of the corresponding original holiday
979 /// codes. See {Iterator Invalidation} for information regarding which
980 /// iterators are affected by the use of this method.
982
983 /// Merge the specified `other` calendar into this calendar such that
984 /// the valid range of this calendar becomes the *union* of the two
985 /// calendars' ranges (or the minimal continuous range spanning the two
986 /// ranges, if the ranges are non-overlapping), and the weekend days
987 /// and holidays for this calendar become the union of those
988 /// (non-business) days from the two calendars -- i.e., the valid
989 /// business days of this calendar become the intersection of those of
990 /// the two calendars after each range is extended to cover the
991 /// resulting one. For each holiday in either calendar, the resulting
992 /// holiday codes in this calendar will be the union of the
993 /// corresponding original holiday codes. See {Iterator Invalidation}
994 /// for information regarding which iterators are affected by the use of
995 /// this method.
997
998 // Aspects
999
1000 /// Assign to this object the value read from the specified input
1001 /// `stream` using the specified `version` format and return a reference
1002 /// to the modifiable `stream`. If `stream` is initially invalid, this
1003 /// operation has no effect. If `stream` becomes invalid during this
1004 /// operation or if `version` is not supported, this object is unaltered.
1005 ///
1006 /// \note Note that no version is read from `stream`. See the
1007 /// `bslx` package-level documentation for more information on BDEX
1008 /// streaming of value-semantic types and containers.
1009 template <class STREAM>
1010 STREAM& bdexStreamIn(STREAM& stream, int version);
1011
1012 /// Efficiently exchange the value of this object with the value of the
1013 /// specified `other` object. This method provides the no-throw exception-safety guarantee.
1014 ///
1015 /// \pre The behavior is undefined unless this
1016 /// object was created with the same allocator as `other`.
1017 void swap(PackedCalendar& other);
1018
1019 // ACCESSORS
1020
1021 /// Return an iterator providing non-modifiable access to the first
1022 /// business day in this calendar. If this calendar has no valid
1023 /// business days, the returned iterator has the same value as that
1024 /// returned by `endBusinessDays()`.
1026
1027 /// Return an iterator providing non-modifiable access to the first
1028 /// business day that occurs on or after the specified `date` in this
1029 /// calendar. If this calendar has no such business day, the returned
1030 /// iterator has the same value as that returned by `endBusinessDays(date)`.
1031 ///
1032 /// \pre The behavior is undefined unless `date` is
1033 /// within the valid range of this calendar.
1035
1036 /// Return an iterator providing non-modifiable access to the first
1037 /// holiday code for the specified `date` in this calendar. If there is
1038 /// no holiday code associated with `date`, the returned iterator has
1039 /// the same value as that returned by `endHolidayCodes(date)`.
1040 ///
1041 /// \pre The behavior is undefined unless `date` is marked as a holiday in this
1042 /// calendar.
1044
1045 /// Return an iterator providing non-modifiable access to the first
1046 /// holiday code for the holiday referenced by the specified `iter`. If
1047 /// there is no holiday code associated with the date referenced by
1048 /// `iter`, the returned iterator has the same value as that returned by `endHolidayCodes(iter)`.
1049 ///
1050 /// \pre The behavior is undefined unless `iter`
1051 /// refers to a valid holiday of this calendar.
1052 HolidayCodeConstIterator beginHolidayCodes(
1053 const HolidayConstIterator& iter) const;
1054
1055 /// Return an iterator providing non-modifiable access to the first
1056 /// holiday in this calendar. If this calendar has no holidays, the
1057 /// returned iterator has the same value as that returned by
1058 /// `endHolidays()`.
1060
1061 /// Return an iterator providing non-modifiable access to the first
1062 /// holiday that occurs on or after the specified `date` in this
1063 /// calendar. If this calendar has no such holiday, the returned
1064 /// iterator has the same value as that returned by `endHolidays(date)`.
1065 ///
1066 /// \pre The behavior is undefined unless `date` is within the valid range
1067 /// of this calendar.
1068 HolidayConstIterator beginHolidays(const Date& date) const;
1069
1070 /// Return an iterator providing non-modifiable access to the first
1071 /// weekend-days transition in the chronological sequence of
1072 /// weekend-days transitions maintained by this calendar. If this
1073 /// calendar has no weekend-days transitions, the returned iterator has
1074 /// the same value as that returned by `endWeekendDaysTransitions()`.
1076
1077 /// Return an iterator providing non-modifiable access to the
1078 /// past-the-end business day in this calendar.
1080
1081 /// Return an iterator providing non-modifiable access to the first
1082 /// business day that occurs after the specified `date` in this
1083 /// calendar. If this calendar has no such business day, the returned
1084 /// iterator has the same value as that returned by `endBusinessDays()`.
1085 ///
1086 /// \pre The behavior is undefined unless `date` is
1087 /// within the valid range of this calendar.
1089
1090 /// Return an iterator providing non-modifiable access to the
1091 /// past-the-end holiday code associated with the specified `date`.
1092 ///
1093 /// \pre The behavior is undefined unless `date` is marked as a holiday in this
1094 /// calendar.
1096
1097 /// Return an iterator providing non-modifiable access to the
1098 /// past-the-end holiday code associated with the date referenced by the specified `iter`.
1099 ///
1100 /// \pre The behavior is undefined unless `iter`
1101 /// references a valid holiday in this calendar.
1103 endHolidayCodes(const HolidayConstIterator& iter) const;
1104
1105 /// Return an iterator providing non-modifiable access to the
1106 /// past-the-end holiday in the chronological sequence of holidays
1107 /// maintained by this calendar.
1109
1110 /// Return an iterator providing non-modifiable access to the first
1111 /// holiday that occurs after the specified `date` in this calendar.
1112 /// If this calendar has no such holiday, the returned iterator has the
1113 /// same value as that returned by `endHolidays()`.
1114 ///
1115 /// \pre The behavior is undefined unless `date` is within the valid range of this calendar.
1116 HolidayConstIterator endHolidays(const Date& date) const;
1117
1118 /// Return an iterator providing non-modifiable access to the
1119 /// past-the-end weekend-days transition in the chronological sequence
1120 /// of weekend-days transitions maintained by this calendar.
1122
1123 /// Return a reference providing non-modifiable access to the earliest
1124 /// date in the valid range of this calendar.
1125 ///
1126 /// \pre The behavior is undefined unless this calendar is non-empty -- i.e., unless
1127 /// `1 <= length()`.
1128 const Date& firstDate() const;
1129
1130 /// Load, into the specified `nextBusinessDay`, the date of the first
1131 /// business day in this calendar following the specified `date`.
1132 /// Return 0 on success -- i.e., if such a business day exists, and a
1133 /// non-zero value (with no effect on `nextBusinessDay`) otherwise.
1134 ///
1135 /// \pre The behavior is undefined unless `date + 1` is both a valid `bdlt::Date`
1136 /// and within the valid range of this calendar.
1137 int getNextBusinessDay(Date *nextBusinessDay, const Date& date) const;
1138
1139 /// Load, into the specified `nextBusinessDay`, the date of the
1140 /// specified `nth` business day in this calendar following the
1141 /// specified `date`. Return 0 on success -- i.e., if such a business
1142 /// day exists, and a non-zero value (with no effect on `nextBusinessDay`) otherwise.
1143 ///
1144 /// \pre The behavior is undefined unless
1145 /// `date + 1` is both a valid `bdlt::Date` and within the valid range
1146 /// of this calendar, and `0 < nth`.
1147 int getNextBusinessDay(Date *nextBusinessDay,
1148 const Date& date,
1149 int nth) const;
1150
1151 /// Return the holiday at the specified `index` in this calendar. For
1152 /// all `index` values from 0 to `numHolidays() - 1` (inclusive), a
1153 /// unique holiday is returned. The mapping of `index` to holiday is
1154 /// invalidated when the set of holidays is modified by an invocation of
1155 /// `addHoliday`, `addHolidayIfInRange`, `intersectBusinessDays`,
1156 /// `intersectNonBusinessDays`, `removeAll`, `removeHoliday`,
1157 /// `setValidRange`, `unionBusinessDays`, or `unionNonBusinessDays`.
1158 ///
1159 /// \pre The behavior is undefined unless `0 <= index < numHolidays()`.
1160 bdlt::Date holiday(int index) const;
1161
1162 /// Return, for the holiday at the specified `date` in this calendar,
1163 /// the holiday code at the specified `index`. For all `index` values
1164 /// from 0 to `numHolidayCodes(date) - 1` (inclusive), a unique holiday
1165 /// code is returned. The mapping of `index` to holiday code is
1166 /// invalidated when the set of holidays or holiday codes is modified by
1167 /// an invocation of `addHoliday`, `addHolidayCode`,
1168 /// `addHolidayCodeIfInRange`, `addHolidayIfInRange`,
1169 /// `intersectBusinessDays`, `intersectNonBusinessDays`, `removeAll`,
1170 /// `removeHoliday`, `removeHolidayCode`, `setValidRange`,
1171 /// `unionBusinessDays`, or `unionNonBusinessDays`.
1172 ///
1173 /// \pre The behavior is undefined unless `date` is a holiday in this calendar and `0 <= index < numHolidayCodes(date)`.
1174 ///
1175 /// \note Note that this method
1176 /// facilitates testing and generally should not be used by clients; in
1177 /// particular, using this method to iterate over the holiday codes for
1178 /// `date` is less efficient than using a `HolidayCodeConstIterator`.
1179 int holidayCode(const Date& date, int index) const;
1180
1181 /// Return `true` if the specified `date` is a business day (i.e., not
1182 /// a holiday or weekend day) in this calendar, and `false` otherwise.
1183 ///
1184 /// \pre The behavior is undefined unless `date` is within the valid range of
1185 /// this calendar.
1186 bool isBusinessDay(const Date& date) const;
1187
1188 /// Return `true` if the specified `date` is a holiday in this calendar, and `false` otherwise.
1189 ///
1190 /// \pre The behavior is undefined unless `date` is
1191 /// within the valid range of this calendar.
1192 bool isHoliday(const Date& date) const;
1193
1194 /// Return `true` if the specified `date` is within the valid range of
1195 /// this calendar (i.e., `firstDate() <= date <= lastDate()`), and `false` otherwise.
1196 ///
1197 /// \note Note that the valid range for a
1198 /// `PackedCalendar` is empty if its length is 0.
1199 bool isInRange(const Date& date) const;
1200
1201 /// Return `true` if the specified `date` is not a business day (i.e.,
1202 /// is either a holiday or weekend day) in this calendar, and `false` otherwise.
1203 ///
1204 /// \pre The behavior is undefined unless `date` is within the
1205 /// valid range of this calendar. Note that:
1206 /// @code
1207 /// !isBusinessDay(date)
1208 /// @endcode
1209 /// returns the same result.
1210 bool isNonBusinessDay(const Date& date) const;
1211
1212 /// Return `true` if the specified `date` falls on a day of the week
1213 /// that is considered a weekend day in this calendar, and `false` otherwise.
1214 ///
1215 /// \note Note that this method is defined for all `date` values,
1216 /// not just those that fall within the valid range, and may be invoked
1217 /// even on an empty calendar (i.e., having `0 == length()`).
1218 bool isWeekendDay(const Date& date) const;
1219
1220 /// Return `true` if the specified `dayOfWeek` is a weekend day in this calendar, and `false` otherwise.
1221 ///
1222 /// \pre The behavior is undefined unless
1223 /// no weekend-days transitions were added to this calendar via the
1224 /// `addWeekendDaysTransition` method.
1225 bool isWeekendDay(DayOfWeek::Enum dayOfWeek) const;
1226
1227 /// Return a reference providing non-modifiable access to the latest
1228 /// date in the valid range of this calendar.
1229 ///
1230 /// \pre The behavior is undefined unless this calendar is non-empty -- i.e., unless
1231 /// `1 <= length()`.
1232 const Date& lastDate() const;
1233
1234 /// Return the number of days in the valid range of this calendar,
1235 /// which is defined to be 0 if this calendar is empty, and
1236 /// `lastDate() - firstDate() + 1` otherwise.
1237 int length() const;
1238
1239 /// Return the number of days in the valid range of this calendar that
1240 /// are considered business days -- i.e., are neither holidays nor
1241 /// weekend days.
1242 ///
1243 /// \note Note that `numBusinessDays() == length() - numNonBusinessDays()`.
1244 int numBusinessDays() const;
1245
1246 /// Return the number of days in the specified range
1247 /// `[beginDate .. endDate]` of this calendar that are considered
1248 /// business days -- i.e., are neither holidays nor weekend days.
1249 ///
1250 /// \pre The behavior is undefined unless `beginDate` and `endDate` are within
1251 /// the valid range of this calendar, and `beginDate <= endDate`.
1252 int numBusinessDays(const Date& beginDate, const Date& endDate) const;
1253
1254 /// Return the number of (unique) holiday codes associated with the
1255 /// specified `date` in this calendar if `date` is a holiday in this calendar, and 0 otherwise.
1256 ///
1257 /// \pre The behavior is undefined unless `date`
1258 /// is within the valid range of this calendar.
1259 int numHolidayCodes(const Date& date) const;
1260
1261 /// Return the total number of holiday codes for all holidays in this calendar.
1262 ///
1263 /// \note Note that this function is used primarily in conjunction
1264 /// with `reserveHolidayCodeCapacity`.
1265 int numHolidayCodesTotal() const;
1266
1267 /// Return the number of days in the valid range of this calendar that
1268 /// are individually marked as holidays, irrespective of whether or not
1269 /// the date is also considered a weekend day.
1270 int numHolidays() const;
1271
1272 /// Return the number of days in the valid range of this calendar that
1273 /// are *not* considered business days -- i.e., are either holidays,
1274 /// weekend days, or both.
1275 ///
1276 /// \note Note that `numNonBusinessDays() == length() - numBusinessDays()`.
1278
1279 /// Return the number of days in the valid range of this calendar that
1280 /// are considered weekend days, irrespective of any designated
1281 /// holidays.
1283
1284 /// Return the number of weekend-days transitions maintained by this
1285 /// calendar.
1286 int numWeekendDaysTransitions() const;
1287
1288 /// Return an iterator providing non-modifiable access to the last
1289 /// business day in this calendar. If this calendar has no valid
1290 /// business days, the returned iterator has the same value as that
1291 /// returned by `rendBusinessDays()`.
1293
1294 /// Return an iterator providing non-modifiable access to the first
1295 /// business day that occurs on or before the specified `date` in this
1296 /// calendar. If this calendar has no such business day, the returned
1297 /// iterator has the same value as that returned by `rendBusinessDays(date)`.
1298 ///
1299 /// \pre The behavior is undefined unless `date`
1300 /// is within the valid range of this calendar.
1302
1303 /// Return an iterator providing non-modifiable access to the last
1304 /// holiday code associated with the specified `date` in this calendar.
1305 /// If there are no holiday codes associated with `date`, the returned
1306 /// iterator has the same value as that returned by `rendHolidayCodes(date)`.
1307 ///
1308 /// \pre The behavior is undefined unless `date`
1309 /// is marked as a holiday in this calendar.
1311
1312 /// Return an iterator providing non-modifiable access to the last
1313 /// holiday code associated with the holiday referenced by the specified
1314 /// `iter`. If there are no holiday codes associated with the date
1315 /// referenced by `iter`, the returned iterator has the same value as
1316 /// that returned by `rendHolidayCodes(iter)`.
1317 ///
1318 /// \pre The behavior is undefined unless `iter` refers to a valid holiday of this calendar.
1320 rbeginHolidayCodes(const HolidayConstIterator& iter) const;
1321
1322 /// Return an iterator providing non-modifiable access to the last
1323 /// holiday in this calendar. If this calendar has no holidays, the
1324 /// returned iterator has the same value as that returned by
1325 /// `rendHolidays()`.
1327
1328 /// Return an iterator providing non-modifiable access to the first
1329 /// holiday that occurs on or before the specified `date` in this
1330 /// calendar. If this calendar has no such holiday, the returned
1331 /// iterator has the same value as that returned by `rendHolidays(date)`.
1332 ///
1333 /// \pre The behavior is undefined unless `date` is
1334 /// within the valid range of this calendar.
1336
1337 /// Return an iterator providing non-modifiable access to the last
1338 /// weekend-days transition in the chronological sequence of
1339 /// weekend-days transitions maintained by this calendar. If this
1340 /// calendar has no weekend-days transitions, the returned iterator has
1341 /// the same value as that returned by `rendWeekendDaysTransitions()`.
1344
1345 /// Return an iterator providing non-modifiable access to the element
1346 /// one before the first business day in this calendar.
1348
1349 /// Return an iterator providing non-modifiable access to the first
1350 /// business day that occurs before the specified `date` in this
1351 /// calendar. If this calendar has no such business day, the returned
1352 /// iterator has the same value as that returned by `rendBusinessDays()`.
1353 ///
1354 /// \pre The behavior is undefined unless `date` is
1355 /// within the valid range of this calendar.
1357
1358 /// Return an iterator providing non-modifiable access to the element
1359 /// one before the first holiday code associated with the specified `date`.
1360 ///
1361 /// \pre The behavior is undefined unless `date` is marked as a
1362 /// holiday in this calendar.
1364
1365 /// Return an iterator providing non-modifiable access to the element
1366 /// one before the first holiday code associated with the holiday
1367 /// referenced by the specified `iter`.
1368 ///
1369 /// \pre The behavior is undefined unless `iter` references a valid holiday in this calendar.
1371 rendHolidayCodes(const HolidayConstIterator& iter) const;
1372
1373 /// Return an iterator providing non-modifiable access to the element
1374 /// one before the first holiday in this calendar.
1376
1377 /// Return an iterator providing non-modifiable access to the first
1378 /// holiday that occurs before the specified `date` in this calendar.
1379 /// If this calendar has no such holiday, the returned iterator has the
1380 /// same value as that returned by `rendHolidays()`.
1381 ///
1382 /// \pre The behavior is undefined unless `date` is within the valid range of this calendar.
1384
1385 /// Return an iterator providing non-modifiable access to the element
1386 /// one before the first weekend-days transition in the chronological
1387 /// sequence of weekend-days transitions maintained by this calendar.
1390
1391 /// Return the weekend-days transition at the specified `index` in this
1392 /// calendar. For all `index` values from 0 to
1393 /// `numWeekendDaysTransitions() - 1` (inclusive), a unique weekend-days
1394 /// transition is returned. The mapping of `index` to weekend-days
1395 /// transition is invalidated when the set of weekend-days transitions
1396 /// is modified by an invocation of `addWeekendDay`, `addWeekendDays`,
1397 /// `addWeekendDaysTransition`, `intersectBusinessDays`,
1398 /// `intersectNonBusinessDays`, `removeAll`, `unionBusinessDays`, or `unionNonBusinessDays`.
1399 ///
1400 /// \pre The behavior is undefined unless
1401 /// `0 <= index < numWeekendDaysTransitions()`.
1403
1404 // Aspects
1405
1406 /// Return the allocator used by this object to supply memory.
1407 bslma::Allocator *allocator() const;
1408
1409 /// Write this value to the specified output `stream` using the
1410 /// specified `version` format and return a reference to the modifiable
1411 /// `stream`. If `version` is not supported, `stream` is unmodified.
1412 ///
1413 /// \note Note that `version` is not written to `stream`. See the `bslx`
1414 /// package-level documentation for more information on BDEX streaming
1415 /// of value-semantic types and containers.
1416 template <class STREAM>
1417 STREAM& bdexStreamOut(STREAM& stream, int version) const;
1418
1419 /// Format this object to the specified output `stream` at the (absolute
1420 /// value of) the optionally specified indentation `level` and return a
1421 /// reference to the modifiable `stream`. If `level` is specified,
1422 /// optionally specify `spacesPerLevel`, the number of spaces per
1423 /// indentation level for this and all of its nested objects. If
1424 /// `level` is negative, suppress indentation of the first line. If
1425 /// `spacesPerLevel` is negative, format the entire output on one line,
1426 /// suppressing all but the initial indentation (as governed by
1427 /// `level`). If `stream` is not valid on entry, this operation has no
1428 /// effect.
1429 bsl::ostream& print(bsl::ostream& stream,
1430 int level = 0,
1431 int spacesPerLevel = 4) const;
1432
1433#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE2.22
1434
1435 // DEPRECATED METHODS
1436
1437 /// Return the most current BDEX streaming version number supported by
1438 /// this class.
1439 ///
1440 /// @deprecated Use @ref maxSupportedBdexVersion(int) instead.
1441 static int maxSupportedBdexVersion();
1442
1443#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE2.22
1444};
1445
1446// FREE OPERATORS
1447
1448/// Return `true` if the specified `lhs` and `rhs` calendars have the same
1449/// value, and `false` otherwise. Two calendars have the same value if they
1450/// have the same valid range (or are both empty), the same weekend days,
1451/// the same holidays, and each corresponding pair of holidays has the same
1452/// (ordered) set of associated holiday codes.
1453bool operator==(const PackedCalendar& lhs, const PackedCalendar& rhs);
1454
1455/// Return `true` if the specified `lhs` and `rhs` calendars do not have the
1456/// same value, and `false` otherwise. Two calendars do not have the same
1457/// value if they do not have the same valid range (and are not both empty),
1458/// do not have the same weekend days, do not have the same holidays, or,
1459/// for at least one corresponding pair of holidays, do not have the same
1460/// (ordered) set of associated holiday codes.
1461bool operator!=(const PackedCalendar& lhs, const PackedCalendar& rhs);
1462
1463/// Write the value of the specified `calendar` to the specified output
1464/// `stream`, and return a reference to the modifiable `stream`.
1465bsl::ostream& operator<<(bsl::ostream& stream,
1466 const PackedCalendar& calendar);
1467
1468// FREE FUNCTIONS
1469
1470/// Pass the specified `object` to the specified `hashAlg`. This function
1471/// integrates with the `bslh` modular hashing system and effectively
1472/// provides a `bsl::hash` specialization for `PackedCalendar`.
1473template <class HASHALG>
1474void hashAppend(HASHALG& hashAlg, const PackedCalendar& object);
1475
1476/// Exchange the values of the specified `a` and `b` objects. This function
1477/// provides the no-throw exception-safety guarantee if the two objects were
1478/// created with the same allocator and the basic guarantee otherwise.
1480
1481 // ==============================
1482 // class PackedCalendar_DateProxy
1483 // ==============================
1484
1485/// This class serves as a proxy for `Date` for use by the arrow operator of
1486/// calendar iterators (e.g., `PackedCalendar_HolidayConstIterator`). An
1487/// object of this class behaves as the `Date` object with which it was
1488/// constructed.
1489///
1490/// See @ref bdlt_packedcalendar
1492
1493 // DATA
1494 Date d_date; // proxied date
1495
1496 private:
1497 // NOT IMPLEMENTED
1499
1500 public:
1501 // CREATORS
1502
1503 /// Create a proxy object for the specified `date`.
1504 PackedCalendar_DateProxy(const Date& date); // IMPLICIT
1505
1506 /// Destroy this object.
1508
1509 /// Create a proxy object referencing the same `Date` value as the
1510 /// specified `original` proxy.
1512
1513 // ACCESSORS
1514
1515 /// Return the address providing non-modifiable access to the proxied
1516 /// date object.
1517 const Date *operator->() const;
1518};
1519
1520 // ============================
1521 // class PackedCalendar_DateRef
1522 // ============================
1523
1524/// This private class is used by the arrow operator of the holiday
1525/// iterator and business day iterator classes. The objects instantiated
1526/// from this class serve as references to `Date` objects.
1527///
1528/// See @ref bdlt_packedcalendar
1530
1531 private:
1532 // NOT IMPLEMENTED
1534
1535 public:
1536 // CREATORS
1537
1538 /// Create a date reference object using the specified `date`.
1539 explicit PackedCalendar_DateRef(const Date& date);
1540
1541 /// Create a date reference object having the value of the specified
1542 /// `original` object.
1544
1545 /// Destroy this object.
1547
1548 // ACCESSORS
1549
1550 /// Return a proxy object to this object's referenced date.
1552};
1553
1554 // =========================================
1555 // class PackedCalendar_HolidayConstIterator
1556 // =========================================
1557
1558/// Provide read-only, sequential access in increasing (chronological) order
1559/// to the holidays in a `PackedCalendar` object. This class owns an
1560/// iterator into the `bdlc::PackedIntArray` storing the holiday offsets of
1561/// the referenced `bdlt::PackedCalendar` and a date, `d_firstDate`, to
1562/// convert the offsets into dates corresponding to holidays.
1563///
1564/// See @ref bdlt_packedcalendar
1566
1567 // DATA
1568 bdlc::PackedIntArray<int>::const_iterator d_iterator; // array's iterator
1569
1570 Date d_firstDate; // offset date
1571
1572 // FRIENDS
1573 friend class PackedCalendar;
1578
1579 private:
1580 // PRIVATE TYPES
1582
1583 // PRIVATE CREATORS
1584
1585 /// Create a holiday iterator using the specified `iter` and
1586 /// `firstDate`.
1588 const Date firstDate);
1589
1590 public:
1591 // TYPES
1593 typedef int difference_type;
1595
1596 /// The star operator returns a `PackedCalendar_DateRef` *by* *value*.
1598
1599#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE3.0
1600
1601 typedef bsl::bidirectional_iterator_tag iterator_category;
1602
1603#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE3.0
1604
1605
1606 // CREATORS
1607
1608 /// Create an iterator having the value of the specified `original`
1609 /// iterator.
1611 const PackedCalendar_HolidayConstIterator& original);
1612
1613 /// Destroy this object.
1615
1616 // MANIPULATORS
1617
1618 /// Assign to this iterator the value of the specified `rhs` iterator,
1619 /// and return a reference providing modifiable access to this object.
1622
1623 /// Advance this iterator to refer to the next holiday in the calendar,
1624 /// and return a reference providing modifiable access to this object.
1625 ///
1626 /// \pre The behavior is undefined unless, on entry, this iterator
1627 /// references a valid holiday.
1629
1630 /// Regress this iterator to refer to the previous holiday in the
1631 /// calendar, and return a reference providing modifiable access to this object.
1632 ///
1633 /// \pre The behavior is undefined unless, on entry, this iterator
1634 /// references a valid holiday that is not the first holiday in the
1635 /// associated calendar.
1637
1638 // ACCESSORS
1639
1640 /// Return a `PackedCalendar_DateRef` object that contains the date
1641 /// value of the holiday referenced by this iterator.
1643
1644 /// Return a date proxy for the holiday referenced by this iterator.
1646};
1647
1648// FREE OPERATORS
1649
1650/// Return `true` if the specified `lhs` and `rhs` iterators refer to the
1651/// same element in the same calendar, and `false` otherwise.
1652///
1653/// \pre The behavior is undefined unless `lhs` and `rhs` both iterate over the same calendar.
1654bool operator==(const PackedCalendar_HolidayConstIterator& lhs,
1656
1657/// Return `true` if the specified `lhs` and `rhs` iterators do not refer to
1658/// the same element in the same calendar, and `false` otherwise.
1659///
1660/// \pre The behavior is undefined unless `lhs` and `rhs` both iterate over the same
1661/// calendar.
1662bool operator!=(const PackedCalendar_HolidayConstIterator& lhs,
1664
1665/// Advance the specified `iterator` to refer to the next holiday in the
1666/// associated calendar, and return the previous value of `iterator`.
1667///
1668/// \pre The behavior is undefined unless, on entry, `iterator` references a valid
1669/// holiday.
1672
1673/// Regress the specified `iterator` to refer to the previous holiday in the
1674/// associated calendar, and return the previous value of `iterator`.
1675///
1676/// \pre The behavior is undefined unless, on entry, `iterator` references a valid
1677/// holiday that is not the first holiday in the associated calendar.
1680
1681 // =============================================
1682 // class PackedCalendar_HolidayCodeConstIterator
1683 // =============================================
1684
1685/// Provide read-only, sequential access in increasing (numerical) order to
1686/// the holiday codes in a `PackedCalendar` object.
1687///
1688/// See @ref bdlt_packedcalendar
1690
1691 // DATA
1692 bdlc::PackedIntArray<int>::const_iterator d_iterator; // array's iterator
1693
1694 // FRIENDS
1695 friend class PackedCalendar;
1700 friend bsl::ptrdiff_t operator-(
1703
1704 private:
1705 // PRIVATE TYPES
1707
1708 // PRIVATE CREATORS
1709
1710 /// Create a holiday-code iterator referencing the holiday code
1711 /// referred to by the specified `iter`.
1713 // IMPLICIT
1714
1715 public:
1716 // TYPES
1717 typedef int value_type;
1718 typedef int difference_type;
1719 typedef int *pointer;
1720
1721 /// The star operator returns an `int` *by* *value*.
1722 typedef int reference;
1723
1724#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE3.0
1725
1726 typedef bsl::bidirectional_iterator_tag iterator_category;
1727
1728#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE3.0
1729
1730 // CREATORS
1731
1732 /// Create an object having the value of the specified `original`
1733 /// iterator.
1736
1737 /// Destroy this object.
1739
1740 // MANIPULATORS
1741
1742 /// Assign to this object the value of the specified `rhs` iterator, and
1743 /// return a reference providing modifiable access to this object.
1746
1747 /// Advance this iterator to refer to the next holiday code for the
1748 /// associated date in the associated calendar, and return a reference
1749 /// providing modifiable access to this object.
1750 ///
1751 /// \pre The behavior is undefined unless, on entry, this iterator references a valid
1752 /// holiday code.
1754
1755 /// Regress this iterator to refer to the previous holiday code for the
1756 /// associated date in the associated calendar, and return a reference
1757 /// providing modifiable access to this object.
1758 ///
1759 /// \pre The behavior is undefined unless, on entry, this iterator references a valid
1760 /// holiday code that is not the first holiday code for the associated
1761 /// date in the calendar.
1763
1764 // ACCESSORS
1765
1766 /// Return the holiday code referenced by this iterator.
1767 int operator*() const;
1768};
1769
1770// FREE OPERATORS
1771
1772/// Return `true` if the specified `lhs` and `rhs` iterators refers to the same element, and `false` otherwise.
1773///
1774/// \pre The behavior is undefined unless
1775/// `lhs` and `rhs` both reference the same holiday in the same calendar.
1778
1779/// Return `true` if the specified `lhs` and `rhs` iterators do not refer to
1780/// the same element, and `false` otherwise.
1781///
1782/// \pre The behavior is undefined unless `lhs` and `rhs` both reference the same holiday in the same
1783/// calendar.
1786
1787/// Advance the specified `iterator` to refer to the next holiday code for
1788/// the associated date in the associated calendar, and return the previous value of `iterator`.
1789///
1790/// \pre The behavior is undefined unless, on entry,
1791/// `iterator` references a valid holiday code.
1794
1795/// Regress the specified `iterator` to refer to the previous holiday code
1796/// for the associated date in the associated calendar, and return the previous value of `iterator`.
1797///
1798/// \pre The behavior is undefined unless, on
1799/// entry, `iterator` references a valid holiday code that is not the first
1800/// holiday code for the associated date in the calendar.
1803
1804/// Return the number of elements between specified `lhs` and `rhs`.
1805///
1806/// \pre The behavior is undefined unless `lhs` and `rhs` refer to codes associated
1807/// with the same holiday in the same calendar.
1810
1811 // =============================================
1812 // class PackedCalendar_BusinessDayConstIterator
1813 // =============================================
1814
1815/// Provide read-only, sequential access in increasing (chronological) order
1816/// to the business days in a `PackedCalendar` object.
1817///
1818/// See @ref bdlt_packedcalendar
1820
1821 // DATA
1823 // iterator for the holiday offsets
1824
1825 const PackedCalendar *d_calendar_p;
1826 // pointer to the calendar
1827
1828 int d_currentOffset;
1829 // offset of the date referenced by this iterator from
1830 // 'd_calendar_p->firstDate()'; if
1831 // 'd_endFlag && 0 < d_calendar_p->length()', must equal
1832 // 'd_calendar_p->lastDate() - d_calendar_p->firstDate()';
1833 // if 'd_endFlag && 0 == d_calendar_p->length()', must
1834 // equal 0
1835
1836 bool d_endFlag;
1837 // indicates an 'end' iterator if set to 'true'
1838
1839 // FRIENDS
1840 friend class PackedCalendar;
1845
1846 private:
1847 // PRIVATE TYPES
1849
1850 // PRIVATE CREATORS
1851
1852 /// Create a business day iterator for the specified `calendar`. If the
1853 /// specified `endIterFlag` is `false`, then this iterator references
1854 /// the first business day on or after the specified `startDate`;
1855 /// otherwise, this iterator references one business day *past* the
1856 /// first business day on or after `startDate`. If no business day
1857 /// matching the above specification exists, then this iterator will
1858 /// reference one day past the end of its range.
1860 const Date& startDate,
1861 bool endIterFlag);
1862
1863 // PRIVATE MANIPULATORS
1864
1865 /// Advance this iterator to the next business day.
1866 ///
1867 /// \pre The behavior is undefined unless `false == d_endFlag`.
1868 void nextBusinessDay();
1869
1870 /// Regress this iterator to the previous business day.
1871 ///
1872 /// \pre The behavior is undefined unless `*this != d_calendar_p->beginBusinessDays()`.
1873 void previousBusinessDay();
1874
1875 public:
1876 // TYPES
1878 typedef int difference_type;
1880
1881 /// The star operator returns a `PackedCalendar_DateRef` *by* *value*.
1883
1884#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE3.0
1885
1886 typedef bsl::bidirectional_iterator_tag iterator_category;
1887
1888#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE3.0
1889
1890 // CREATORS
1891
1892 /// Create an iterator having the value of the specified `original`
1893 /// iterator.
1896
1897 /// Destroy this object.
1899
1900 // MANIPULATORS
1901
1902 /// Assign to this iterator the value of the specified `rhs` iterator,
1903 /// and return a reference providing modifiable access to this object.
1906
1907 /// Advance this iterator to refer to the next business day in the
1908 /// associated calendar, and return a reference providing modifiable access to this object.
1909 ///
1910 /// \pre The behavior is undefined unless, on entry,
1911 /// this iterator references a valid business day.
1913
1914 /// Regress this iterator to refer to the previous business day in the
1915 /// associated calendar, and return a reference providing modifiable access to this object.
1916 ///
1917 /// \pre The behavior is undefined unless, on entry,
1918 /// this iterator references a valid business day that is not the first
1919 /// business day for the associated calendar.
1921
1922 // ACCESSORS
1923
1924 /// Return a `PackedCalendar_DateRef` object that contains the date
1925 /// value of the business day referenced by this iterator.
1927
1928 /// Return a date proxy for the business day referenced by this
1929 /// iterator.
1931};
1932
1933// FREE OPERATORS
1934
1935/// Return `true` if the specified `lhs` and `rhs` iterators refer to the
1936/// same element in the same calendar, and `false` otherwise.
1937///
1938/// \pre The behavior is undefined unless `lhs` and `rhs` both iterate over the same calendar.
1941
1942/// Return `true` if the specified `lhs` and `rhs` iterators do not refer to
1943/// the same element in the same calendar, and `false` otherwise.
1944///
1945/// \pre The behavior is undefined unless `lhs` and `rhs` both iterate over the same
1946/// calendar.
1949
1950/// Advance the specified `iterator` to refer to the next business day in
1951/// the associated calendar, and return the previous value of `iterator`.
1952///
1953/// \pre The behavior is undefined unless, on entry, `iterator` references a
1954/// valid business day.
1957
1958/// Regress the specified `iterator` to refer to the previous business day
1959/// in the associated calendar, and return the previous value of `iterator`.
1960///
1961/// \pre The behavior is undefined unless, on entry, `iterator` references a
1962/// valid business day that is not the first business day for the associated
1963/// calendar.
1966
1967// ============================================================================
1968// INLINE DEFINITIONS
1969// ============================================================================
1970
1971 // ------------------------------
1972 // class PackedCalendar_DateProxy
1973 // ------------------------------
1974
1975// CREATORS
1976inline
1978: d_date(date)
1979{
1980}
1981
1982inline
1986
1987inline
1989 const PackedCalendar_DateProxy& original)
1990: d_date(original.d_date)
1991{
1992}
1993
1994// ACCESSORS
1995inline
1997{
1998 return &d_date;
1999}
2000
2001 // ----------------------------
2002 // class PackedCalendar_DateRef
2003 // ----------------------------
2004
2005// CREATORS
2006inline
2008: Date(date)
2009{
2010}
2011
2012inline
2014 const PackedCalendar_DateRef& original)
2015: Date(original)
2016{
2017}
2018
2019inline
2023
2024// ACCESSORS
2025inline
2030
2031 // -----------------------------------------
2032 // class PackedCalendar_HolidayConstIterator
2033 // -----------------------------------------
2034
2035// PRIVATE CREATORS
2036inline
2037PackedCalendar_HolidayConstIterator::
2038 PackedCalendar_HolidayConstIterator(const OffsetsConstIterator& iter,
2039 const Date firstDate)
2040: d_iterator(iter)
2041, d_firstDate(firstDate)
2042{
2043}
2044
2045// CREATORS
2046inline
2047PackedCalendar_HolidayConstIterator::PackedCalendar_HolidayConstIterator(
2049: d_iterator(original.d_iterator)
2050, d_firstDate(original.d_firstDate)
2051{
2052}
2053
2054inline
2058
2059// MANIPULATORS
2060inline
2063{
2064 d_iterator = rhs.d_iterator;
2065 d_firstDate = rhs.d_firstDate;
2066 return *this;
2067}
2068
2069inline
2072{
2073 ++d_iterator;
2074 return *this;
2075}
2076
2077inline
2080{
2081 --d_iterator;
2082 return *this;
2083}
2084
2085// ACCESSORS
2086inline
2091
2092inline
2095{
2096 return PackedCalendar_DateProxy(this->operator*());
2097}
2098
2099} // close package namespace
2100
2101// FREE OPERATORS
2102inline
2103bool bdlt::operator==(const PackedCalendar_HolidayConstIterator& lhs,
2104 const PackedCalendar_HolidayConstIterator& rhs)
2105{
2106 return lhs.d_iterator == rhs.d_iterator;
2107}
2108
2109inline
2110bool bdlt::operator!=(const PackedCalendar_HolidayConstIterator& lhs,
2111 const PackedCalendar_HolidayConstIterator& rhs)
2112{
2113 return lhs.d_iterator != rhs.d_iterator;
2114}
2115
2116inline
2118 bdlt::operator++(PackedCalendar_HolidayConstIterator& iterator, int)
2119{
2120 PackedCalendar_HolidayConstIterator tmp(iterator);
2121 ++iterator;
2122 return tmp;
2123}
2124
2125inline
2127 bdlt::operator--(PackedCalendar_HolidayConstIterator& iterator, int)
2128{
2129 PackedCalendar_HolidayConstIterator tmp(iterator);
2130 --iterator;
2131 return tmp;
2132}
2133
2134namespace bdlt {
2135
2136 // ---------------------------------------------
2137 // class PackedCalendar_HolidayCodeConstIterator
2138 // ---------------------------------------------
2139
2140// PRIVATE CREATORS
2141inline
2142PackedCalendar_HolidayCodeConstIterator::
2143 PackedCalendar_HolidayCodeConstIterator(const CodesConstIterator& iter)
2144: d_iterator(iter)
2145{
2146}
2147
2148// CREATORS
2149inline
2150PackedCalendar_HolidayCodeConstIterator::
2151PackedCalendar_HolidayCodeConstIterator(
2153: d_iterator(original.d_iterator)
2154{
2155}
2156
2157inline
2162
2163// MANIPULATORS
2164inline
2168{
2169 d_iterator = rhs.d_iterator;
2170 return *this;
2171}
2172
2173inline
2176{
2177 ++d_iterator;
2178 return *this;
2179}
2180
2181inline
2184{
2185 --d_iterator;
2186 return *this;
2187}
2188
2189// ACCESSORS
2190inline
2192{
2193 return *d_iterator;
2194}
2195
2196} // close package namespace
2197
2198// FREE OPERATORS
2199inline
2200bool bdlt::operator==(const PackedCalendar_HolidayCodeConstIterator& lhs,
2201 const PackedCalendar_HolidayCodeConstIterator& rhs)
2202{
2203 return lhs.d_iterator == rhs.d_iterator;
2204}
2205
2206inline
2207bool bdlt::operator!=(const PackedCalendar_HolidayCodeConstIterator& lhs,
2208 const PackedCalendar_HolidayCodeConstIterator& rhs)
2209{
2210 return lhs.d_iterator != rhs.d_iterator;
2211}
2212
2213inline
2215 bdlt::operator++(PackedCalendar_HolidayCodeConstIterator& iterator, int)
2216{
2218 ++iterator;
2219 return tmp;
2220}
2221
2222inline
2224 bdlt::operator--(PackedCalendar_HolidayCodeConstIterator& iterator, int)
2225{
2226 PackedCalendar_HolidayCodeConstIterator tmp(iterator);
2227 --iterator;
2228 return tmp;
2229}
2230
2231inline
2232bsl::ptrdiff_t
2233 bdlt::operator-(const PackedCalendar_HolidayCodeConstIterator& lhs,
2234 const PackedCalendar_HolidayCodeConstIterator& rhs)
2235{
2236 return lhs.d_iterator - rhs.d_iterator;
2237}
2238
2239namespace bdlt {
2240
2241 // ---------------------------------------------
2242 // class PackedCalendar_BusinessDayConstIterator
2243 // ---------------------------------------------
2244
2245// CREATORS
2246inline
2247PackedCalendar_BusinessDayConstIterator::
2248PackedCalendar_BusinessDayConstIterator(
2250: d_offsetIter(original.d_offsetIter)
2251, d_calendar_p(original.d_calendar_p)
2252, d_currentOffset(original.d_currentOffset)
2253, d_endFlag(original.d_endFlag)
2254{
2255}
2256
2257inline
2262
2263// MANIPULATORS
2264inline
2267{
2268 BSLS_ASSERT_SAFE(false == d_endFlag);
2269
2270 nextBusinessDay();
2271 return *this;
2272}
2273
2274inline
2277{
2278 BSLS_ASSERT_SAFE(*this != d_calendar_p->beginBusinessDays());
2279
2280 previousBusinessDay();
2281 return *this;
2282}
2283
2284// ACCESSORS
2285inline
2288{
2289 return PackedCalendar_DateRef(d_calendar_p->firstDate() + d_currentOffset);
2290}
2291
2292inline
2295{
2296 return PackedCalendar_DateProxy(this->operator*());
2297}
2298
2299} // close package namespace
2300
2301// FREE OPERATORS
2302inline
2303bool bdlt::operator==(const PackedCalendar_BusinessDayConstIterator& lhs,
2304 const PackedCalendar_BusinessDayConstIterator& rhs)
2305{
2306 BSLS_ASSERT_SAFE(lhs.d_calendar_p == rhs.d_calendar_p);
2307
2308 return lhs.d_endFlag == rhs.d_endFlag
2309 && lhs.d_currentOffset == rhs.d_currentOffset;
2310}
2311
2312inline
2313bool bdlt::operator!=(const PackedCalendar_BusinessDayConstIterator& lhs,
2314 const PackedCalendar_BusinessDayConstIterator& rhs)
2315{
2316 BSLS_ASSERT_SAFE(lhs.d_calendar_p == rhs.d_calendar_p);
2317
2318 return lhs.d_endFlag != rhs.d_endFlag
2319 || lhs.d_currentOffset != rhs.d_currentOffset;
2320}
2321
2322inline
2324 PackedCalendar_BusinessDayConstIterator& iterator, int)
2325{
2326 PackedCalendar_BusinessDayConstIterator tmp(iterator);
2327 ++iterator;
2328 return tmp;
2329}
2330
2331inline
2333 PackedCalendar_BusinessDayConstIterator& iterator, int)
2334{
2335 PackedCalendar_BusinessDayConstIterator tmp(iterator);
2336 --iterator;
2337 return tmp;
2338}
2339
2340namespace bdlt {
2341
2342 // --------------------
2343 // class PackedCalendar
2344 // --------------------
2345
2346// PRIVATE ACCESSORS
2347inline
2348PackedCalendar::CodesConstIterator
2349 PackedCalendar::beginHolidayCodes(const OffsetsConstIterator& iter) const
2350{
2351 BSLS_ASSERT_SAFE(isHoliday(d_firstDate + *iter));
2352
2353 const int indexOffset = static_cast<int>(iter - d_holidayOffsets.begin());
2354
2355 const bsl::size_t codeOffset = d_holidayCodesIndex[indexOffset];
2356
2357 return d_holidayCodes.begin() + codeOffset;
2358}
2359
2360inline
2361PackedCalendar::CodesConstIterator
2362 PackedCalendar::endHolidayCodes(const OffsetsConstIterator& iter) const
2363{
2364 BSLS_ASSERT_SAFE(isHoliday(d_firstDate + *iter));
2365
2366 const bsl::size_t endIndexOffset = iter - d_holidayOffsets.begin() + 1;
2367
2368 const bsl::size_t iterIndex = endIndexOffset ==
2369 d_holidayCodesIndex.length()
2370 ? d_holidayCodes.length()
2371 : d_holidayCodesIndex[endIndexOffset];
2372 return d_holidayCodes.begin() + iterIndex;
2373}
2374
2375// CLASS METHODS
2376
2377 // Aspects
2378
2379inline
2381{
2382 if (versionSelector >= 20150612) {
2383 return 3; // RETURN
2384 }
2385 return 2;
2386}
2387
2388// MANIPULATORS
2389inline
2390int PackedCalendar::addHolidayCodeIfInRange(const Date& date, int holidayCode)
2391{
2392 if (isInRange(date)) {
2394 return 0; // RETURN
2395 }
2396 return -1;
2397}
2398
2399inline
2401{
2402 if (isInRange(date)) {
2403 addHoliday(date);
2404 return 0; // RETURN
2405 }
2406 return -1;
2407}
2408
2409inline
2411{
2413
2414 d_holidayOffsets.reserveCapacity(numHolidays);
2415 d_holidayCodesIndex.reserveCapacity(numHolidays);
2416}
2417
2418inline
2420{
2422
2423 d_holidayCodes.reserveCapacity(numHolidayCodes);
2424}
2425
2426 // Aspects
2427
2428template <class STREAM>
2429STREAM& PackedCalendar::bdexStreamIn(STREAM& stream, int version)
2430{
2431 if (stream) {
2432 switch (version) { // Switch on the schema version (starting with 1).
2433 case 3: {
2435 firstDate.bdexStreamIn(stream, 1);
2436
2437 if (!stream) {
2438 return stream; // RETURN
2439 }
2440
2442 lastDate.bdexStreamIn(stream, 1);
2443
2444 if (!stream
2445 || (firstDate > lastDate
2446 && (firstDate != Date(9999,12,31)
2447 || lastDate != Date(1,1,1)))) {
2448 stream.invalidate();
2449 return stream; // RETURN
2450 }
2451
2452 int length = lastDate - firstDate + 1;
2453
2454 int transitionsLength = 0;
2455 stream.getLength(transitionsLength);
2456
2457 if (!stream || transitionsLength < 0) {
2458 stream.invalidate();
2459 return stream; // RETURN
2460 }
2461
2463 weekendDaysTransitions(transitionsLength, d_allocator_p);
2464 for (int i = 0; i < transitionsLength; ++i) {
2465 WeekendDaysTransition& wdt = weekendDaysTransitions[i];
2466
2467 wdt.first.bdexStreamIn(stream, 1);
2468
2469 if (!stream) {
2470 return stream; // RETURN
2471 }
2472
2473 // The data must be monotonically increasing.
2474
2475 if (i && wdt.first <= weekendDaysTransitions[i - 1].first) {
2476 stream.invalidate();
2477 return stream; // RETURN
2478 }
2479
2480 wdt.second.bdexStreamIn(stream, 1);
2481
2482 if (!stream) {
2483 return stream; // RETURN
2484 }
2485 }
2486
2487 bdlc::PackedIntArray<int> holidayOffsets(d_allocator_p);
2488 holidayOffsets.bdexStreamIn(stream, 1);
2489
2490 if (!stream
2491 || (firstDate > lastDate && !holidayOffsets.isEmpty())
2492 || (firstDate <= lastDate
2493 && (static_cast<int>(holidayOffsets.length()) > length
2494 || (!holidayOffsets.isEmpty()
2495 && (holidayOffsets[0] < 0
2496 || holidayOffsets[0] > length))))) {
2497 stream.invalidate();
2498 return stream; // RETURN
2499 }
2500
2501 // The values in 'holidayOffsets' must be monotonically increasing
2502 // and represent dates within the valid range.
2503
2504 for (bsl::size_t i = 1; i < holidayOffsets.length(); ++i) {
2505 if (holidayOffsets[i - 1] >= holidayOffsets[i]
2506 || holidayOffsets[i] > length) {
2507 stream.invalidate();
2508 return stream; // RETURN
2509 }
2510 }
2511
2512 bdlc::PackedIntArray<int> holidayCodesIndex(d_allocator_p);
2513 holidayCodesIndex.bdexStreamIn(stream, 1);
2514
2515 if (!stream
2516 || holidayCodesIndex.length() != holidayOffsets.length()
2517 || (!holidayCodesIndex.isEmpty() && holidayCodesIndex[0] != 0)) {
2518 stream.invalidate();
2519 return stream; // RETURN
2520 }
2521
2522 // The values in 'holidayCodesIndex' must be monotonically
2523 // non-decreasing.
2524
2525 for (bsl::size_t i = 1; i < holidayCodesIndex.length(); ++i) {
2526 if (holidayCodesIndex[i - 1] > holidayCodesIndex[i]) {
2527 stream.invalidate();
2528 return stream; // RETURN
2529 }
2530 }
2531
2532 bdlc::PackedIntArray<int> holidayCodes(d_allocator_p);
2533 holidayCodes.bdexStreamIn(stream, 1);
2534
2535 if (!stream
2536 || (holidayOffsets.isEmpty() && !holidayCodes.isEmpty())) {
2537 stream.invalidate();
2538 return stream; // RETURN
2539 }
2540
2541 // The values in the segments of 'holidayOffsets' must be
2542 // monotonically increasing.
2543
2544 bsl::size_t index = 0;
2545 for (int i = 0; i < static_cast<int>(holidayCodes.length()); ++i) {
2546 if (index < holidayCodesIndex.length()
2547 && i == holidayCodesIndex[index]) {
2548 ++index;
2549 while (index < holidayCodesIndex.length()
2550 && i == holidayCodesIndex[index]) {
2551 ++index;
2552 }
2553 }
2554 else if (holidayCodes[i - 1] >= holidayCodes[i]) {
2555 stream.invalidate();
2556 return stream; // RETURN
2557 }
2558 }
2559
2560 bslalg::SwapUtil::swap(&d_firstDate, &firstDate);
2561 bslalg::SwapUtil::swap(&d_lastDate, &lastDate);
2562 bslalg::SwapUtil::swap(&d_weekendDaysTransitions,
2563 &weekendDaysTransitions);
2564 bslalg::SwapUtil::swap(&d_holidayOffsets, &holidayOffsets);
2565 bslalg::SwapUtil::swap(&d_holidayCodesIndex, &holidayCodesIndex);
2566 bslalg::SwapUtil::swap(&d_holidayCodes, &holidayCodes);
2567 } break;
2568 case 2: {
2569 PackedCalendar inCal(d_allocator_p);
2570 inCal.d_firstDate.bdexStreamIn(stream, 1);
2571 if (!stream) {
2572 return stream; // RETURN
2573 }
2574
2575 inCal.d_lastDate.bdexStreamIn(stream, 1);
2576 if (!stream
2577 || (inCal.d_firstDate > inCal.d_lastDate
2578 && (inCal.d_firstDate != Date(9999,12,31)
2579 || inCal.d_lastDate != Date(1,1,1)))) {
2580 stream.invalidate();
2581 return stream; // RETURN
2582 }
2583 int length = inCal.d_lastDate - inCal.d_firstDate + 1;
2584
2585 int transitionsLength = 0;
2586 stream.getLength(transitionsLength);
2587 if (!stream || transitionsLength < 0)
2588 {
2589 stream.invalidate();
2590 return stream; // RETURN
2591 }
2592
2593 int offsetsLength = 0;
2594 stream.getLength(offsetsLength);
2595 if (!stream
2596 || (inCal.d_firstDate > inCal.d_lastDate
2597 && offsetsLength != 0)
2598 || (inCal.d_firstDate <= inCal.d_lastDate
2599 && (offsetsLength < 0 || offsetsLength > length))) {
2600 stream.invalidate();
2601 return stream; // RETURN
2602 }
2603 BSLS_ASSERT(offsetsLength >= 0);
2604
2605 int codesLength = 0;
2606 stream.getLength(codesLength);
2607 if (!stream || (0 == offsetsLength && codesLength != 0)) {
2608 stream.invalidate();
2609 return stream; // RETURN
2610 }
2611
2612 inCal.d_weekendDaysTransitions.resize(transitionsLength);
2613
2614 // To ensure 'inCal' cannot be in an invalid state, we must first
2615 // reserve capacity for the three 'PackedIntArray' and then resize
2616 // them to guarantee the operations can complete without
2617 // re-allocation *and* the object invariants (see the destructor
2618 // implementation) are maintained.
2619
2620 inCal.d_holidayOffsets.reserveCapacity(offsetsLength);
2621 inCal.d_holidayCodesIndex.reserveCapacity(offsetsLength);
2622 inCal.d_holidayCodes.reserveCapacity(codesLength);
2623
2624 inCal.d_holidayOffsets.resize(offsetsLength);
2625 inCal.d_holidayCodesIndex.resize(offsetsLength);
2626 inCal.d_holidayCodes.resize(codesLength);
2627
2628 for (WeekendDaysTransitionSequence::iterator it =
2629 inCal.d_weekendDaysTransitions.begin();
2630 it != inCal.d_weekendDaysTransitions.end();
2631 ++it) {
2632 it->first.bdexStreamIn(stream, 1);
2633 if (!stream) {
2634 return stream; // RETURN
2635 }
2636
2637 if (it != inCal.d_weekendDaysTransitions.begin()
2638 && it->first <= (it - 1)->first) {
2639 stream.invalidate();
2640 return stream; // RETURN
2641 }
2642
2643 it->second.bdexStreamIn(stream, 1);
2644 if (!stream) {
2645 return stream; // RETURN
2646 }
2647 }
2648
2649 int previousValue = -1;
2650 for (int i = 0; i < offsetsLength; ++i) {
2651 int tmp;
2652 stream.getInt32(tmp);
2653 if (!stream
2654 || tmp < 0
2655 || tmp >= length
2656 || tmp <= previousValue) {
2657 stream.invalidate();
2658 return stream; // RETURN
2659 }
2660 inCal.d_holidayOffsets.replace(i, tmp);
2661 previousValue = tmp;
2662 }
2663
2664 previousValue = -1;
2665 for (int i = 0; i < offsetsLength; ++i) {
2666 int tmp;
2667 stream.getInt32(tmp);
2668
2669 // This vector is ordered but duplicates are allowed. The
2670 // first element must be 0.
2671
2672 if (!stream
2673 || tmp < 0
2674 || tmp < previousValue
2675 || tmp > codesLength
2676 || (0 == i && 0 != tmp)) {
2677
2678 // If we get here, some of the code indices could
2679 // potentially be greater than 'codesLength'. That would
2680 // trigger an assertion in the destructor. So call
2681 // 'removeAll' to clean up.
2682
2683 inCal.removeAll();
2684 stream.invalidate();
2685 return stream; // RETURN
2686 }
2687 inCal.d_holidayCodesIndex.replace(i, tmp);
2688 previousValue = tmp;
2689 }
2690
2691 CodesIndexConstIterator it = inCal.d_holidayCodesIndex.begin();
2692 CodesIndexConstIterator end = inCal.d_holidayCodesIndex.end();
2693
2694 // Skip the holidays that have no codes.
2695
2696 while (it != end && 0 == *it) {
2697 ++it;
2698 }
2699
2700 // 'it' is now positioned at the first holiday with one or more
2701 // codes or at the end.
2702
2703 bool previousValueFlag = false; // This flag is used to determine
2704 // if we are inside an ordered
2705 // sequence of codes (i.e.,
2706 // 'previousValue' refers to a
2707 // code for the same holiday as
2708 // 'value').
2709
2710 for (int i = 0; i < codesLength; ++i) {
2711 int tmp;
2712 stream.getInt32(tmp);
2713 if (!stream
2714 || (previousValueFlag && tmp <= previousValue)) {
2715 stream.invalidate();
2716 return stream; // RETURN
2717 }
2718 inCal.d_holidayCodes.replace(i, tmp);
2719
2720 // Regardless of whether or not there is more data, advance the
2721 // index iterator as needed and update 'previousValueFlag' if
2722 // 'it' moves.
2723
2724 if (it != end && i == (*it - 1)) {
2725 previousValueFlag = false;
2726
2727 while (it != end && i == (*it - 1)) {
2728 ++it; // Skip the holidays that have no codes.
2729 }
2730 }
2731 else {
2732 previousValueFlag = true;
2733 }
2734 previousValue = tmp;
2735 }
2736 BSLS_ASSERT(it == end);
2737
2738 swap(inCal); // This cannot throw.
2739 } break;
2740 case 1: {
2741 PackedCalendar inCal(d_allocator_p);
2742 inCal.d_firstDate.bdexStreamIn(stream, 1);
2743 if (!stream) {
2744 return stream; // RETURN
2745 }
2746
2747 inCal.d_lastDate.bdexStreamIn(stream, 1);
2748 if (!stream
2749 || (inCal.d_firstDate > inCal.d_lastDate
2750 && (inCal.d_firstDate != Date(9999, 12, 31)
2751 || inCal.d_lastDate != Date(1, 1, 1)))) {
2752 stream.invalidate();
2753 return stream; // RETURN
2754 }
2755 int length = inCal.d_lastDate - inCal.d_firstDate + 1;
2756
2757 DayOfWeekSet weekendDays;
2758 weekendDays.bdexStreamIn(stream, 1);
2759 if (!stream) {
2760 return stream; // RETURN
2761 }
2762
2763 if (weekendDays.length() > 0) {
2764 inCal.addWeekendDays(weekendDays);
2765 }
2766
2767 int offsetsLength = 0;
2768 stream.getLength(offsetsLength);
2769 if (!stream
2770 || (inCal.d_firstDate > inCal.d_lastDate
2771 && offsetsLength != 0)
2772 || (inCal.d_firstDate <= inCal.d_lastDate
2773 && (offsetsLength < 0 || offsetsLength > length))) {
2774 stream.invalidate();
2775 return stream; // RETURN
2776 }
2777 BSLS_ASSERT(offsetsLength >= 0);
2778
2779 int codesLength = 0;
2780 stream.getLength(codesLength);
2781 if (!stream || (0 == offsetsLength && codesLength != 0)) {
2782 stream.invalidate();
2783 return stream; // RETURN
2784 }
2785
2786 // To ensure 'inCal' cannot be in an invalid state, we must first
2787 // reserve capacity for the three 'PackedIntArray' and then resize
2788 // them to guarantee the operations can complete without
2789 // re-allocation *and* the object invariants (see the destructor
2790 // implementation) are maintained.
2791
2792 inCal.d_holidayOffsets.reserveCapacity(offsetsLength);
2793 inCal.d_holidayCodesIndex.reserveCapacity(offsetsLength);
2794 inCal.d_holidayCodes.reserveCapacity(codesLength);
2795
2796 inCal.d_holidayOffsets.resize(offsetsLength);
2797 inCal.d_holidayCodesIndex.resize(offsetsLength);
2798 inCal.d_holidayCodes.resize(codesLength);
2799
2800 int previousValue = -1;
2801 for (int i = 0; i < offsetsLength; ++i) {
2802 int tmp;
2803 stream.getInt32(tmp);
2804 if (!stream
2805 || tmp < 0
2806 || tmp >= length
2807 || tmp <= previousValue) {
2808 stream.invalidate();
2809 return stream; // RETURN
2810 }
2811 inCal.d_holidayOffsets.replace(i, tmp);
2812 previousValue = tmp;
2813 }
2814
2815 previousValue = -1;
2816 for (int i = 0; i < offsetsLength; ++i) {
2817 int tmp;
2818 stream.getInt32(tmp);
2819
2820 // This vector is ordered but duplicates are allowed. The
2821 // first element must be 0.
2822
2823 if (!stream
2824 || tmp < 0
2825 || tmp < previousValue
2826 || tmp > codesLength
2827 || (0 == i && 0 != tmp)) {
2828
2829 // If we get here, some of the code indices could
2830 // potentially be greater than 'codesLength'. That would
2831 // trigger an assertion in the destructor. So call
2832 // 'removeAll' to clean up.
2833
2834 inCal.removeAll();
2835 stream.invalidate();
2836 return stream; // RETURN
2837 }
2838 inCal.d_holidayCodesIndex.replace(i, tmp);
2839 previousValue = tmp;
2840 }
2841
2842 CodesIndexConstIterator it = inCal.d_holidayCodesIndex.begin();
2843 CodesIndexConstIterator end = inCal.d_holidayCodesIndex.end();
2844
2845 // Skip the holidays that have no codes.
2846
2847 while (it != end && 0 == *it) {
2848 ++it;
2849 }
2850
2851 // 'it' is now positioned at the first holiday with one or more
2852 // codes or at the end.
2853
2854 bool previousValueFlag = false; // This flag is used to determine
2855 // if we are inside an ordered
2856 // sequence of codes (i.e.,
2857 // 'previousValue' refers to a
2858 // code for the same holiday as
2859 // 'value').
2860
2861 for (int i = 0; i < codesLength; ++i) {
2862 int tmp;
2863 stream.getInt32(tmp);
2864 if (!stream
2865 || (previousValueFlag && tmp <= previousValue)) {
2866 stream.invalidate();
2867 return stream; // RETURN
2868 }
2869 inCal.d_holidayCodes.replace(i, tmp);
2870
2871 // Regardless of whether or not there is more data, advance the
2872 // index iterator as needed and update 'previousValueFlag' if
2873 // 'it' moves.
2874
2875 if (it != end && i == (*it - 1)) {
2876 previousValueFlag = false;
2877
2878 while (it != end && i == (*it - 1)) {
2879 ++it; // Skip the holidays that have no codes.
2880 }
2881 }
2882 else {
2883 previousValueFlag = true;
2884 }
2885 previousValue = tmp;
2886 }
2887 BSLS_ASSERT(it == end);
2888
2889 swap(inCal); // This cannot throw.
2890 } break;
2891 default: {
2892 stream.invalidate();
2893 }
2894 }
2895 }
2896 return stream;
2897}
2898
2899// ACCESSORS
2900inline
2903{
2904 return BusinessDayConstIterator(*this, d_firstDate, false);
2905}
2906
2907inline
2910{
2912
2913 return BusinessDayConstIterator(*this, date, false);
2914}
2915
2916inline
2918 PackedCalendar::beginHolidayCodes(const HolidayConstIterator& iter) const
2919{
2921
2922 return HolidayCodeConstIterator(beginHolidayCodes(iter.d_iterator));
2923}
2924
2925inline
2927{
2928 return HolidayConstIterator(d_holidayOffsets.begin(), d_firstDate);
2929}
2930
2931inline
2934{
2936
2938 d_holidayOffsets.begin(),
2939 d_holidayOffsets.end(),
2940 date - d_firstDate);
2941 return HolidayConstIterator(i, d_firstDate);
2942}
2943
2944inline
2947{
2948 return d_weekendDaysTransitions.begin();
2949}
2950
2951inline
2954{
2955 return BusinessDayConstIterator(*this, d_lastDate, true);
2956}
2957
2958inline
2961{
2963
2964 return BusinessDayConstIterator(*this, date, true);
2965}
2966
2967inline
2969 PackedCalendar::endHolidayCodes(const HolidayConstIterator& iter) const
2970{
2972
2973 return endHolidayCodes(iter.d_iterator);
2974}
2975
2976inline
2978{
2979 return HolidayConstIterator(d_holidayOffsets.end(), d_firstDate);
2980}
2981
2982inline
2985{
2987
2989 d_holidayOffsets.begin(),
2990 d_holidayOffsets.end(),
2991 date - d_firstDate);
2992 return HolidayConstIterator(i, d_firstDate);
2993}
2994
2995inline
2998{
2999 return d_weekendDaysTransitions.end();
3000}
3001
3002inline
3004{
3005 BSLS_ASSERT_SAFE(d_firstDate <= d_lastDate);
3006
3007 return d_firstDate;
3008}
3009
3010inline
3012 const Date& date) const
3013{
3014 BSLS_ASSERT_SAFE(nextBusinessDay);
3015 BSLS_ASSERT_SAFE(Date(9999, 12, 31) > date);
3016 BSLS_ASSERT_SAFE(isInRange(date + 1));
3017
3018 enum { e_SUCCESS = 0, e_FAILURE = 1 };
3019
3021 if (iter == endBusinessDays()) {
3022 return e_FAILURE; // RETURN
3023 }
3024 *nextBusinessDay = *iter;
3025 return e_SUCCESS;
3026}
3027
3028inline
3030{
3031 BSLS_ASSERT_SAFE(0 <= index);
3032 BSLS_ASSERT_SAFE( index < numHolidays());
3033
3034 return d_firstDate + d_holidayOffsets[index];
3035}
3036
3037inline
3038int PackedCalendar::holidayCode(const Date& date, int index) const
3039{
3042 BSLS_ASSERT_SAFE(0 <= index);
3043 BSLS_ASSERT_SAFE( index < numHolidayCodes(date));
3044
3045 const int offset = date - d_firstDate;
3046 const OffsetsConstIterator offsetBegin = d_holidayOffsets.begin();
3047 const OffsetsConstIterator offsetEnd = d_holidayOffsets.end();
3049 offsetBegin,
3050 offsetEnd,
3051 offset);
3052 return d_holidayCodes[d_holidayCodesIndex[i - offsetBegin] + index];
3053}
3054
3055inline
3057{
3059
3060 return !isNonBusinessDay(date);
3061}
3062
3063inline
3064bool PackedCalendar::isHoliday(const Date& date) const
3065{
3067
3068 const int offset = date - d_firstDate;
3069 const OffsetsConstIterator offsetEnd = d_holidayOffsets.end();
3071 d_holidayOffsets.begin(),
3072 offsetEnd,
3073 offset);
3074
3075 return i != offsetEnd && *i == offset;
3076}
3077
3078inline
3079bool PackedCalendar::isInRange(const Date& date) const
3080{
3081 return d_firstDate <= date && date <= d_lastDate;
3082}
3083
3084inline
3086{
3088
3089 return isWeekendDay(date) || isHoliday(date);
3090}
3091
3092inline
3094{
3096 BSLS_ASSERT_SAFE(d_weekendDaysTransitions.size() <= 1);
3098
3099 if (d_weekendDaysTransitions.empty()) {
3100 return false; // RETURN
3101 }
3102
3103 BSLS_ASSERT_SAFE(d_weekendDaysTransitions[0].first == Date(1,1,1));
3104
3105 return d_weekendDaysTransitions[0].second.isMember(dayOfWeek);
3106}
3107
3108inline
3110{
3111 BSLS_ASSERT_SAFE(d_firstDate <= d_lastDate);
3112
3113 return d_lastDate;
3114}
3115
3116inline
3118{
3119 return d_firstDate <= d_lastDate ? d_lastDate - d_firstDate + 1 : 0;
3120}
3121
3122inline
3124{
3125 return length() - numNonBusinessDays();
3126}
3127
3128inline
3130{
3131 return static_cast<int>(d_holidayCodes.length());
3132}
3133
3134inline
3136{
3137 return static_cast<int>(d_holidayOffsets.length());
3138}
3139
3140inline
3142{
3143 return static_cast<int>(d_weekendDaysTransitions.size());
3144}
3145
3146inline
3152
3153inline
3156{
3158
3160}
3161
3162inline
3165{
3167
3168 return HolidayCodeConstReverseIterator(endHolidayCodes(date));
3169}
3170
3171inline
3174{
3176
3177 return HolidayCodeConstReverseIterator(endHolidayCodes(iter));
3178}
3179
3180inline
3186
3187inline
3190{
3192
3194}
3195
3196inline
3199{
3201 d_weekendDaysTransitions.end());
3202}
3203
3204inline
3210
3211inline
3214{
3216
3218}
3219
3220inline
3223{
3225
3226 return HolidayCodeConstReverseIterator(beginHolidayCodes(date));
3227}
3228
3229inline
3232{
3234
3235 return HolidayCodeConstReverseIterator(beginHolidayCodes(iter));
3236}
3237
3238inline
3244
3245inline
3248{
3250
3252}
3253
3254inline
3257{
3259 d_weekendDaysTransitions.begin());
3260}
3261
3262inline
3265{
3266 BSLS_ASSERT_SAFE(0 <= index);
3268
3269 return d_weekendDaysTransitions[index];
3270}
3271
3272 // Aspects
3273
3274inline
3276{
3277 return d_allocator_p;
3278}
3279
3280template <class STREAM>
3281STREAM& PackedCalendar::bdexStreamOut(STREAM& stream, int version) const
3282{
3283 switch (version) { // Switch on the schema version (starting with 1).
3284 case 3: {
3285 d_firstDate.bdexStreamOut(stream, 1);
3286 d_lastDate.bdexStreamOut(stream, 1);
3287
3288 stream.putLength(static_cast<int>(d_weekendDaysTransitions.size()));
3289 for (WeekendDaysTransitionSequence::size_type i = 0;
3290 i < d_weekendDaysTransitions.size();
3291 ++i) {
3292 d_weekendDaysTransitions[i].first.bdexStreamOut(stream, 1);
3293 d_weekendDaysTransitions[i].second.bdexStreamOut(stream, 1);
3294 }
3295
3296 d_holidayOffsets.bdexStreamOut(stream, 1);
3297 d_holidayCodesIndex.bdexStreamOut(stream, 1);
3298 d_holidayCodes.bdexStreamOut(stream, 1);
3299 } break;
3300 case 2: {
3301 d_firstDate.bdexStreamOut(stream, 1);
3302 d_lastDate.bdexStreamOut(stream, 1);
3303
3304 stream.putLength(static_cast<int>(d_weekendDaysTransitions.size()));
3305 stream.putLength(static_cast<int>(d_holidayOffsets.length()));
3306 stream.putLength(static_cast<int>(d_holidayCodes.length()));
3307
3308 for (WeekendDaysTransitionSequence::size_type i = 0;
3309 i < d_weekendDaysTransitions.size();
3310 ++i) {
3311 d_weekendDaysTransitions[i].first.bdexStreamOut(stream, 1);
3312 d_weekendDaysTransitions[i].second.bdexStreamOut(stream, 1);
3313 }
3314
3315 for (bsl::size_t i = 0; i < d_holidayOffsets.length(); ++i) {
3316 stream.putInt32(d_holidayOffsets[i]);
3317 }
3318 for (bsl::size_t i = 0; i < d_holidayCodesIndex.length(); ++i) {
3319 stream.putInt32(d_holidayCodesIndex[i]);
3320 }
3321 for (bsl::size_t i = 0; i < d_holidayCodes.length(); ++i) {
3322 stream.putInt32(d_holidayCodes[i]);
3323 }
3324 } break;
3325 case 1: {
3327 "bdlt::packedCalendar::bdexStreamOut deprecated version");
3328
3329 d_firstDate.bdexStreamOut(stream, 1);
3330 d_lastDate.bdexStreamOut(stream, 1);
3331
3332 if (!d_weekendDaysTransitions.empty() &&
3333 d_weekendDaysTransitions[0].first == Date(1, 1, 1)) {
3334 d_weekendDaysTransitions[0].second.bdexStreamOut(stream, 1);
3335 }
3336 else {
3337 DayOfWeekSet tempSet;
3338 tempSet.bdexStreamOut(stream, 1);
3339 }
3340
3341 stream.putLength(static_cast<int>(d_holidayOffsets.length()));
3342 stream.putLength(static_cast<int>(d_holidayCodes.length()));
3343
3344 for (bsl::size_t i = 0; i < d_holidayOffsets.length(); ++i) {
3345 stream.putInt32(d_holidayOffsets[i]);
3346 }
3347 for (bsl::size_t i = 0; i < d_holidayCodesIndex.length(); ++i) {
3348 stream.putInt32(d_holidayCodesIndex[i]);
3349 }
3350 for (bsl::size_t i = 0; i < d_holidayCodes.length(); ++i) {
3351 stream.putInt32(d_holidayCodes[i]);
3352 }
3353 } break;
3354 default: {
3355 stream.invalidate();
3356 }
3357
3358 }
3359 return stream;
3360}
3361
3362#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE2.22
3363
3364// DEPRECATED METHODS
3365inline
3367{
3368 return 1;
3369}
3370
3371#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE2.22
3372
3373} // close package namespace
3374
3375// FREE OPERATORS
3376inline
3377bool bdlt::operator!=(const PackedCalendar& lhs, const PackedCalendar& rhs)
3378{
3379 return !(lhs == rhs);
3380}
3381
3382// FREE FUNCTIONS
3383template <class HASHALG>
3384inline
3385void bdlt::hashAppend(HASHALG& hashAlg, const PackedCalendar& object)
3386{
3387 using ::BloombergLP::bslh::hashAppend;
3388 hashAppend(hashAlg, object.d_firstDate);
3389 hashAppend(hashAlg, object.d_lastDate);
3390 hashAppend(hashAlg, object.d_weekendDaysTransitions);
3391 hashAppend(hashAlg, object.d_holidayOffsets);
3392 hashAppend(hashAlg, object.d_holidayCodesIndex);
3393 hashAppend(hashAlg, object.d_holidayCodes);
3394}
3395
3396
3397
3398// TRAITS
3399
3400namespace bslma {
3401
3402template <>
3403struct UsesBslmaAllocator<bdlt::PackedCalendar> : bsl::true_type {};
3404
3405} // close namespace bslma
3406
3407
3408#endif
3409
3410// ----------------------------------------------------------------------------
3411// Copyright 2018 Bloomberg Finance L.P.
3412//
3413// Licensed under the Apache License, Version 2.0 (the "License");
3414// you may not use this file except in compliance with the License.
3415// You may obtain a copy of the License at
3416//
3417// http://www.apache.org/licenses/LICENSE-2.0
3418//
3419// Unless required by applicable law or agreed to in writing, software
3420// distributed under the License is distributed on an "AS IS" BASIS,
3421// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3422// See the License for the specific language governing permissions and
3423// limitations under the License.
3424// ----------------------------- END-OF-FILE ----------------------------------
3425
3426/** @} */
3427/** @} */
3428/** @} */
Definition bdlc_packedintarray.h:802
Definition bdlc_packedintarray.h:1098
const_iterator end() const
Definition bdlc_packedintarray.h:2633
STREAM & bdexStreamOut(STREAM &stream, int version) const
Definition bdlc_packedintarray.h:2604
const_iterator begin() const
Definition bdlc_packedintarray.h:2612
bool isEmpty() const
Definition bdlc_packedintarray.h:2649
STREAM & bdexStreamIn(STREAM &stream, int version)
Definition bdlc_packedintarray.h:2393
void resize(bsl::size_t numElements)
Definition bdlc_packedintarray.h:2561
bsl::size_t length() const
Return number of elements in this array.
Definition bdlc_packedintarray.h:2663
void reserveCapacity(bsl::size_t numElements)
Definition bdlc_packedintarray.h:2528
void replace(bsl::size_t dstIndex, TYPE value)
Definition bdlc_packedintarray.h:2500
Definition bdlt_calendarreverseiteratoradapter.h:298
Definition bdlt_date.h:294
STREAM & bdexStreamOut(STREAM &stream, int version) const
Definition bdlt_date.h:1013
STREAM & bdexStreamIn(STREAM &stream, int version)
Definition bdlt_date.h:924
Definition bdlt_dayofweekset.h:402
STREAM & bdexStreamIn(STREAM &stream, int version)
Definition bdlt_dayofweekset.h:820
int length() const
Return the number of elements in this set.
Definition bdlt_dayofweekset.h:876
STREAM & bdexStreamOut(STREAM &stream, int version) const
Definition bdlt_dayofweekset.h:896
Definition bdlt_packedcalendar.h:1819
PackedCalendar_DateProxy operator->() const
Definition bdlt_packedcalendar.h:2294
PackedCalendar_BusinessDayConstIterator & operator++()
Definition bdlt_packedcalendar.h:2266
int difference_type
Definition bdlt_packedcalendar.h:1878
PackedCalendar_DateProxy pointer
Definition bdlt_packedcalendar.h:1879
Date value_type
Definition bdlt_packedcalendar.h:1877
PackedCalendar_DateRef reference
The star operator returns a PackedCalendar_DateRef by value.
Definition bdlt_packedcalendar.h:1882
friend bool operator!=(const PackedCalendar_BusinessDayConstIterator &, const PackedCalendar_BusinessDayConstIterator &)
PackedCalendar_BusinessDayConstIterator & operator=(const PackedCalendar_BusinessDayConstIterator &rhs)
bsl::bidirectional_iterator_tag iterator_category
Definition bdlt_packedcalendar.h:1886
friend bool operator==(const PackedCalendar_BusinessDayConstIterator &, const PackedCalendar_BusinessDayConstIterator &)
PackedCalendar_BusinessDayConstIterator & operator--()
Definition bdlt_packedcalendar.h:2276
PackedCalendar_DateRef operator*() const
Definition bdlt_packedcalendar.h:2287
~PackedCalendar_BusinessDayConstIterator()
Destroy this object.
Definition bdlt_packedcalendar.h:2259
Definition bdlt_packedcalendar.h:1491
PackedCalendar_DateProxy(const Date &date)
Create a proxy object for the specified date.
Definition bdlt_packedcalendar.h:1977
~PackedCalendar_DateProxy()
Destroy this object.
Definition bdlt_packedcalendar.h:1983
const Date * operator->() const
Definition bdlt_packedcalendar.h:1996
Definition bdlt_packedcalendar.h:1529
~PackedCalendar_DateRef()
Destroy this object.
Definition bdlt_packedcalendar.h:2020
PackedCalendar_DateProxy operator&() const
Return a proxy object to this object's referenced date.
Definition bdlt_packedcalendar.h:2026
PackedCalendar_DateRef(const Date &date)
Create a date reference object using the specified date.
Definition bdlt_packedcalendar.h:2007
Definition bdlt_packedcalendar.h:1689
friend bool operator!=(const PackedCalendar_HolidayCodeConstIterator &, const PackedCalendar_HolidayCodeConstIterator &)
friend bsl::ptrdiff_t operator-(const PackedCalendar_HolidayCodeConstIterator &, const PackedCalendar_HolidayCodeConstIterator &)
PackedCalendar_HolidayCodeConstIterator & operator=(const PackedCalendar_HolidayCodeConstIterator &rhs)
Definition bdlt_packedcalendar.h:2167
PackedCalendar_HolidayCodeConstIterator & operator--()
Definition bdlt_packedcalendar.h:2183
int value_type
Definition bdlt_packedcalendar.h:1717
int reference
The star operator returns an int by value.
Definition bdlt_packedcalendar.h:1722
~PackedCalendar_HolidayCodeConstIterator()
Destroy this object.
Definition bdlt_packedcalendar.h:2159
int operator*() const
Return the holiday code referenced by this iterator.
Definition bdlt_packedcalendar.h:2191
bsl::bidirectional_iterator_tag iterator_category
Definition bdlt_packedcalendar.h:1726
int difference_type
Definition bdlt_packedcalendar.h:1718
friend bool operator==(const PackedCalendar_HolidayCodeConstIterator &, const PackedCalendar_HolidayCodeConstIterator &)
int * pointer
Definition bdlt_packedcalendar.h:1719
PackedCalendar_HolidayCodeConstIterator & operator++()
Definition bdlt_packedcalendar.h:2175
Definition bdlt_packedcalendar.h:1565
PackedCalendar_HolidayConstIterator & operator--()
Definition bdlt_packedcalendar.h:2079
PackedCalendar_DateProxy pointer
Definition bdlt_packedcalendar.h:1594
PackedCalendar_HolidayConstIterator & operator++()
Definition bdlt_packedcalendar.h:2071
~PackedCalendar_HolidayConstIterator()
Destroy this object.
Definition bdlt_packedcalendar.h:2055
bsl::bidirectional_iterator_tag iterator_category
Definition bdlt_packedcalendar.h:1601
int difference_type
Definition bdlt_packedcalendar.h:1593
PackedCalendar_HolidayConstIterator & operator=(const PackedCalendar_HolidayConstIterator &rhs)
Definition bdlt_packedcalendar.h:2062
friend bool operator==(const PackedCalendar_HolidayConstIterator &, const PackedCalendar_HolidayConstIterator &)
Date value_type
Definition bdlt_packedcalendar.h:1592
PackedCalendar_DateRef operator*() const
Definition bdlt_packedcalendar.h:2087
friend bool operator!=(const PackedCalendar_HolidayConstIterator &, const PackedCalendar_HolidayConstIterator &)
PackedCalendar_DateRef reference
The star operator returns a PackedCalendar_DateRef by value.
Definition bdlt_packedcalendar.h:1597
PackedCalendar_DateProxy operator->() const
Return a date proxy for the holiday referenced by this iterator.
Definition bdlt_packedcalendar.h:2094
Definition bdlt_packedcalendar.h:593
void reserveHolidayCodeCapacity(int numHolidayCodes)
Definition bdlt_packedcalendar.h:2419
HolidayConstReverseIterator rbeginHolidays() const
Definition bdlt_packedcalendar.h:3182
int getNextBusinessDay(Date *nextBusinessDay, const Date &date) const
Definition bdlt_packedcalendar.h:3011
void addWeekendDays(const DayOfWeekSet &weekendDays)
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
bool isBusinessDay(const Date &date) const
Definition bdlt_packedcalendar.h:3056
bdlt::CalendarReverseIteratorAdapter< HolidayConstIterator > HolidayConstReverseIterator
Definition bdlt_packedcalendar.h:642
PackedCalendar(bslma::Allocator *basicAllocator=0)
void addHoliday(const Date &date)
PackedCalendar_HolidayConstIterator HolidayConstIterator
Definition bdlt_packedcalendar.h:634
void unionBusinessDays(const PackedCalendar &other)
int numWeekendDaysInRange() const
PackedCalendar(const Date &firstDate, const Date &lastDate, bslma::Allocator *basicAllocator=0)
int numNonBusinessDays() const
void setValidRange(const Date &firstDate, const Date &lastDate)
friend bool operator!=(const PackedCalendar &, const PackedCalendar &)
const Date & firstDate() const
Definition bdlt_packedcalendar.h:3003
int numBusinessDays(const Date &beginDate, const Date &endDate) const
void addHolidayCode(const Date &date, int holidayCode)
int numHolidays() const
Definition bdlt_packedcalendar.h:3135
int getNextBusinessDay(Date *nextBusinessDay, const Date &date, int nth) const
int numHolidayCodesTotal() const
Definition bdlt_packedcalendar.h:3129
void removeHoliday(const Date &date)
WeekendDaysTransitionConstReverseIterator rendWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:3256
HolidayCodeConstReverseIterator rendHolidayCodes(const Date &date) const
Definition bdlt_packedcalendar.h:3222
int holidayCode(const Date &date, int index) const
Definition bdlt_packedcalendar.h:3038
WeekendDaysTransitionConstIterator endWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:2997
HolidayCodeConstIterator beginHolidayCodes(const Date &date) const
WeekendDaysTransitionSequence::const_iterator WeekendDaysTransitionConstIterator
Definition bdlt_packedcalendar.h:648
PackedCalendar_HolidayCodeConstIterator HolidayCodeConstIterator
Definition bdlt_packedcalendar.h:636
void removeHolidayCode(const Date &date, int holidayCode)
BusinessDayConstReverseIterator rendBusinessDays() const
Definition bdlt_packedcalendar.h:3206
BusinessDayConstReverseIterator rbeginBusinessDays() const
Definition bdlt_packedcalendar.h:3148
BusinessDayConstIterator endBusinessDays() const
Definition bdlt_packedcalendar.h:2953
void addWeekendDay(DayOfWeek::Enum weekendDay)
int numBusinessDays() const
Definition bdlt_packedcalendar.h:3123
STREAM & bdexStreamIn(STREAM &stream, int version)
Definition bdlt_packedcalendar.h:2429
void addWeekendDaysTransition(const Date &startDate, const DayOfWeekSet &weekendDays)
void reserveHolidayCapacity(int numHolidays)
Definition bdlt_packedcalendar.h:2410
bool isNonBusinessDay(const Date &date) const
Definition bdlt_packedcalendar.h:3085
HolidayConstIterator beginHolidays() const
Definition bdlt_packedcalendar.h:2926
const Date & lastDate() const
Definition bdlt_packedcalendar.h:3109
bdlt::CalendarReverseIteratorAdapter< HolidayCodeConstIterator > HolidayCodeConstReverseIterator
Definition bdlt_packedcalendar.h:645
WeekendDaysTransitionPrivate WeekendDaysTransition
Definition bdlt_packedcalendar.h:630
bool isHoliday(const Date &date) const
Definition bdlt_packedcalendar.h:3064
HolidayCodeConstReverseIterator rbeginHolidayCodes(const Date &date) const
Definition bdlt_packedcalendar.h:3164
void swap(PackedCalendar &other)
void intersectNonBusinessDays(const PackedCalendar &other)
WeekendDaysTransition weekendDaysTransition(int index) const
Definition bdlt_packedcalendar.h:3264
HolidayCodeConstIterator endHolidayCodes(const Date &date) const
HolidayConstIterator endHolidays() const
Definition bdlt_packedcalendar.h:2977
~PackedCalendar()
Destroy this object.
void unionNonBusinessDays(const PackedCalendar &other)
bool isInRange(const Date &date) const
Definition bdlt_packedcalendar.h:3079
void intersectBusinessDays(const PackedCalendar &other)
bsl::reverse_iterator< WeekendDaysTransitionSequence::const_iterator > WeekendDaysTransitionConstReverseIterator
Definition bdlt_packedcalendar.h:652
bdlt::CalendarReverseIteratorAdapter< BusinessDayConstIterator > BusinessDayConstReverseIterator
Definition bdlt_packedcalendar.h:639
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlt_packedcalendar.h:3275
int length() const
Definition bdlt_packedcalendar.h:3117
bdlt::Date holiday(int index) const
Definition bdlt_packedcalendar.h:3029
static int maxSupportedBdexVersion()
Definition bdlt_packedcalendar.h:3366
STREAM & bdexStreamOut(STREAM &stream, int version) const
Definition bdlt_packedcalendar.h:3281
PackedCalendar(const PackedCalendar &original, bslma::Allocator *basicAllocator=0)
int addHolidayIfInRange(const Date &date)
Definition bdlt_packedcalendar.h:2400
int numWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:3141
PackedCalendar & operator=(const PackedCalendar &rhs)
WeekendDaysTransitionConstIterator beginWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:2946
BusinessDayConstIterator beginBusinessDays() const
Definition bdlt_packedcalendar.h:2902
HolidayConstReverseIterator rendHolidays() const
Definition bdlt_packedcalendar.h:3240
WeekendDaysTransitionConstReverseIterator rbeginWeekendDaysTransitions() const
Definition bdlt_packedcalendar.h:3198
friend bool operator==(const PackedCalendar &, const PackedCalendar &)
void addDay(const Date &date)
bool isWeekendDay(const Date &date) const
int numHolidayCodes(const Date &date) const
int addHolidayCodeIfInRange(const Date &date, int holidayCode)
Definition bdlt_packedcalendar.h:2390
PackedCalendar_BusinessDayConstIterator BusinessDayConstIterator
Definition bdlt_packedcalendar.h:632
friend void hashAppend(HASHALG &hashAlg, const PackedCalendar &)
Definition bslstl_pair.h:1280
Definition bslstl_vector.h:1120
static void swap(T *a, T *b)
Definition bslalg_swaputil.h:182
Definition bslma_allocator.h:545
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_PRECONDITIONS_END()
Definition bsls_preconditions.h:131
#define BSLS_PRECONDITIONS_BEGIN()
Definition bsls_preconditions.h:130
#define BSLS_REVIEW_INVOKE(X)
Definition bsls_review.h:911
void hashAppend(HASH_ALGORITHM &hashAlgorithm, const BigEndianInt16 &object)
Definition bbldc_basicisma30360.h:112
Calendar_BusinessDayConstIter operator++(Calendar_BusinessDayConstIter &iterator, int)
Definition bdlt_calendar.h:2215
bool operator==(const Calendar &lhs, const Calendar &rhs)
Date operator-(const Date &date, int numDays)
bsl::ostream & operator<<(bsl::ostream &stream, const Calendar &calendar)
void hashAppend(HASHALG &hashAlg, const Calendar &object)
bool operator!=(const Calendar &lhs, const Calendar &rhs)
Calendar_BusinessDayConstIter operator--(Calendar_BusinessDayConstIter &iterator, int)
Definition bdlt_calendar.h:2224
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
Definition baljsn_encoder_testtypes.h:76
static PackedIntArrayConstIterator< TYPE > upperBound(PackedIntArrayConstIterator< TYPE > first, PackedIntArrayConstIterator< TYPE > last, TYPE value)
Definition bdlc_packedintarrayutil.h:221
static PackedIntArrayConstIterator< TYPE > lowerBound(PackedIntArrayConstIterator< TYPE > first, PackedIntArrayConstIterator< TYPE > last, TYPE value)
Definition bdlc_packedintarrayutil.h:191
Enum
Enumerated day-of-week values.
Definition bdlt_dayofweek.h:125
Definition bslma_usesbslmaallocator.h:344