BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlt_date.h
Go to the documentation of this file.
1/// @file bdlt_date.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlt_date.h -*-C++-*-
8#ifndef INCLUDED_BDLT_DATE
9#define INCLUDED_BDLT_DATE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlt_date bdlt_date
15/// @brief Provide a value-semantic type to represent dates.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlt
19/// @{
20/// @addtogroup bdlt_date
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlt_date-purpose"> Purpose</a>
25/// * <a href="#bdlt_date-classes"> Classes </a>
26/// * <a href="#bdlt_date-description"> Description </a>
27/// * <a href="#bdlt_date-valid-date-values-and-their-representations"> Valid Date Values and Their Representations </a>
28/// * <a href="#bdlt_date-ensuring-bdlt-date-validity"> Ensuring bdlt::Date Validity </a>
29/// * <a href="#bdlt_date-bdex-compatibility-with-legacy-posix-based-date"> BDEX Compatibility with Legacy POSIX-Based Date </a>
30/// * <a href="#bdlt_date-iso-standard-text-representation"> ISO Standard Text Representation </a>
31/// * <a href="#bdlt_date-usage"> Usage </a>
32/// * <a href="#bdlt_date-example-1-basic-use-of-bdlt-date"> Example 1: Basic Use of bdlt::Date </a>
33///
34/// # Purpose {#bdlt_date-purpose}
35/// Provide a value-semantic type to represent dates.
36///
37/// # Classes {#bdlt_date-classes}
38///
39/// - bdlt::Date: value-semantic date type consistent with the Unix calendar
40///
41/// @see bdlt_dayofweek, bdlt_serialdateimputil, bdlt_dateformatter,
42/// bdlt_formatdoc
43///
44/// # Description {#bdlt_date-description}
45/// This component defines a value-semantic class, `bdlt::Date`,
46/// capable of representing any valid date that is consistent with the Unix
47/// (POSIX) calendar restricted to the years 1 through 9999 (inclusive):
48/// @code
49/// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cal.html
50/// @endcode
51/// "Actual" (i.e., natural) day and date calculations are supported directly by
52/// `bdlt::Date` and its associated free operators. Calculations involving
53/// business days (or holidays), and day-count conventions (e.g., "ISMA30360"),
54/// can be found elsewhere.
55///
56/// See @ref bdlt_calendar and the `bbldc` day-count convention package.
57///
58/// ## Valid Date Values and Their Representations {#bdlt_date-valid-date-values-and-their-representations}
59///
60///
61/// A `bdlt::Date` object *always* represents a valid date value as defined by
62/// the standard Unix calendar. The value of a `bdlt::Date` object can be
63/// expressed in the interface as either `(year, month, day)`, the canonical
64/// representation of dates, or `(year, dayOfYear)`. For example,
65/// `(1959, 3, 8)` represents the same valid `bdlt::Date` value as `(1959, 67)`
66/// because the 8th day of the 3rd month of the year 1959 is also the 67th day
67/// of the year 1959.
68///
69/// Of course, not all combinations of `(year, month, day)` and
70/// `(year, dayOfYear)` constitute valid values for `bdlt::Date` objects. A
71/// `(year, dayOfYear)` pair does *not* represent a valid `bdlt::Date` value
72/// unless `1 <= year <= 9999` and `1 <= dayOfYear <= 366`. Additionally, if
73/// `year` is not a leap year, then the representation is not valid unless
74/// `1 <= dayOfYear <= 365`.
75///
76/// In a leap year, February has 29 days instead of the usual 28. (Thus, leap
77/// years have 366 days instead of the usual 365.) Prior to 1752, the Unix
78/// calendar follows the convention of the Julian calendar: every year divisible
79/// by 4 is a leap year. After 1752, the Unix calendar follows the (more
80/// accurate) Gregorian calendar: a year is leap year if it is divisible by 4,
81/// but *not* divisible by 100, *unless* it is *also* divisible by 400. Note
82/// that 1752 is the year that Britain and its empire (including the colonies
83/// that later became the United States) switched from the Julian to the
84/// Gregorian calendar. See:
85/// @code
86/// http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar
87/// https://en.wikipedia.org/wiki/Calendar_(New_Style)_Act_1750
88/// @endcode
89/// Moreover, the Unix calendar lacks the dates `[3 .. 13]` in September 1752,
90/// days that were dropped to align British dates with those used on the
91/// European continent. Thus:
92/// @code
93/// assert(++bdlt::Date(1752, 9, 2) == bdlt::Date(1752, 9, 14));
94/// assert( bdlt::Date(1752, 9, 2) == --bdlt::Date(1752, 9, 14));
95/// @endcode
96/// Note that two `static` (class) methods:
97/// @code
98/// bool isValidYearDay(int year, int dayOfYear);
99/// bool isValidYearMonthDay(int year, int month, int day);
100/// @endcode
101/// are provided within `bdlt::Date` to indicate whether the given pair or
102/// triple of integers would represent a valid `bdlt::Date` value (e.g., prior
103/// to using them to construct a `bdlt::Date` object).
104///
105/// ## Ensuring bdlt::Date Validity {#bdlt_date-ensuring-bdlt-date-validity}
106///
107///
108/// Note that it is incumbent on the client of a `bdlt::Date` object never to
109/// cause it, directly or indirectly, to hold an invalid value, which can occur
110/// only by violating explicitly stated preconditions. For example, invoking
111/// `operator++` on a date object that represents the valid `bdlt::Date` value
112/// 9999/12/31 (December 31, 9999) is a contract violation that can lead to
113/// undefined behavior. Similarly, attempting to set the value of an existing
114/// date using the `setYearMonthDay` manipulator such that invoking
115/// `isValidYearMonthDay` would return `false` on the same `(year, month, day)`
116/// arguments is another contract violation.
117///
118/// When setting a `bdlt::Date` object to a particular value, there are two
119/// forms of methods provided for both of the `(year, month, day)` and
120/// `(year, dayOfYear)` representations of date values. When you are *certain*
121/// that the value you are trying to set is valid, either of the following two
122/// runtime-efficient methods can be used safely:
123/// @code
124/// void setYearDay(int year, int dayOfYear);
125/// void setYearMonthDay(int year, int month, int day);
126/// @endcode
127/// If, however, the integral date attributes at hand are not known to represent
128/// a valid date, they must first be validated, e.g., by calling one of the two
129/// `static` `isValid*` methods, or by calling the appropriate set method having
130/// the `IfValid` suffix, which will always verify validity before either
131/// setting the value and returning 0, or returning a non-zero status with no
132/// effect on the object:
133/// @code
134/// int setYearDayIfValid(int year, int dayOfYear);
135/// int setYearMonthDayIfValid(int year, int month, int day);
136/// @endcode
137/// Note that if the value is "known" to be valid, and these latter `IfValid`
138/// variants are called without checking their return status, we run the risk of
139/// a "double fault" in that if the value is not actually valid, there is no way
140/// for a robust implementation (such as this one) to check for the error in a
141/// defensive (e.g., "DEBUG" or "SAFE") build mode.
142///
143/// ## BDEX Compatibility with Legacy POSIX-Based Date {#bdlt_date-bdex-compatibility-with-legacy-posix-based-date}
144///
145///
146/// The version 1 format supported by `bdlt::Date` for BDEX streaming is
147/// expressly intended for maintaining some degree of "compatibility" with
148/// versions of this date class that are built to use the proleptic Gregorian
149/// calendar.
150///
151/// **WARNING**: Use of the proleptic Gregorian version of this class is
152/// *disallowed* in Bloomberg code.
153///
154/// Over the range of dates supported by `bdlt::Date`
155/// (`[0001JAN01 .. 9999DEC31]`), the proleptic Gregorian calendar (used by
156/// `bdlt::Date`) has two fewer days than `cal`, and some dates that exist in
157/// one calendar do not exist in the other; therefore, true compatibility is not
158/// possible. The compatibility guaranteed by BDEX streaming version 1 is such
159/// that all dates in the range `[1752SEP14 .. 9999DEC31]`, as well as the
160/// default value (`0001JAN01`), can be successfully exchanged, via BDEX,
161/// between `bdlt::Date` classes built to use the POSIX calendar and those built
162/// to use the proleptic Gregorian calendar.
163///
164/// ## ISO Standard Text Representation {#bdlt_date-iso-standard-text-representation}
165///
166///
167/// A common standard text representation of a date and time value is described
168/// by ISO 8601. BDE provides the @ref bdlt_iso8601util component for conversion
169/// to and from the standard ISO8601 format.
170///
171/// ## Usage {#bdlt_date-usage}
172///
173///
174/// This section illustrates intended use of this component.
175///
176/// ### Example 1: Basic Use of bdlt::Date {#bdlt_date-example-1-basic-use-of-bdlt-date}
177///
178///
179/// The following snippets of code illustrate how to create and use a
180/// `bdlt::Date` object.
181///
182/// First, we create a default date `d1`:
183/// @code
184/// bdlt::Date d1; assert( 1 == d1.year());
185/// assert( 1 == d1.month());
186/// assert( 1 == d1.day());
187/// @endcode
188/// Next, we set `d1` to July 4, 1776:
189/// @code
190/// d1.setYearMonthDay(1776, 7, 4);
191/// assert(1776 == d1.year());
192/// assert( 7 == d1.month());
193/// assert( 4 == d1.day());
194/// @endcode
195/// We can also use `setYearMonthDayIfValid` if we are not sure whether a
196/// particular year/month/day combination constitutes a valid `bdlt::Date`. For
197/// example, if we want to set `d1` to `1900/02/29`, and it turns out that year
198/// 1900 was not a leap year (it wasn't), there will be no effect on the current
199/// value of the object:
200/// @code
201/// int ret = d1.setYearMonthDayIfValid(1900, 2, 29);
202/// assert( 0 != ret); // 1900 not leap year
203/// assert(1776 == d1.year()); // no effect on `d1`
204/// assert( 7 == d1.month());
205/// assert( 4 == d1.day());
206/// @endcode
207/// Then, from `d1`, we can determine the day of the year, and the day of the
208/// week, of July 4, 1776:
209/// @code
210/// int dayOfYear = d1.dayOfYear();
211/// assert( 186 == dayOfYear);
212///
213/// bdlt::DayOfWeek::Enum dayOfWeek = d1.dayOfWeek();
214/// assert(bdlt::DayOfWeek::e_THU == dayOfWeek);
215/// @endcode
216/// Next, we create a `bdlt::Date` object, `d2`, using the year/day-of-year
217/// representation for dates:
218/// @code
219/// bdlt::Date d2(1776, dayOfYear);
220/// assert(1776 == d2.year());
221/// assert( 186 == d2.dayOfYear());
222/// assert( 7 == d2.month());
223/// assert( 4 == d2.day());
224/// assert( d1 == d2);
225/// @endcode
226/// Then, we add six days to the value of `d2`:
227/// @code
228/// d2 += 6; assert(1776 == d2.year());
229/// assert( 7 == d2.month());
230/// assert( 10 == d2.day());
231/// @endcode
232/// Now, we subtract `d1` from `d2`, storing the (signed) difference in days
233/// (a.k.a. *actual* difference) in `daysDiff`:
234/// @code
235/// int daysDiff = d2 - d1; assert( 6 == daysDiff);
236/// @endcode
237/// Finally, we stream the value of `d2` to `stdout`:
238/// @code
239/// bsl::cout << d2 << bsl::endl;
240/// @endcode
241/// The streaming operator produces:
242/// @code
243/// 10JUL1776
244/// @endcode
245/// on `stdout`.
246/// @}
247/** @} */
248/** @} */
249
250/** @addtogroup bdl
251 * @{
252 */
253/** @addtogroup bdlt
254 * @{
255 */
256/** @addtogroup bdlt_date
257 * @{
258 */
259
260#include <bdlscm_version.h>
261
262#include <bdlt_dayofweek.h>
263#include <bdlt_monthofyear.h>
265
268
269#include <bslh_hash.h>
270
271#include <bsls_assert.h>
272#include <bsls_keyword.h>
273#include <bsls_preconditions.h>
274#include <bsls_review.h>
275
276#include <bsl_iosfwd.h>
277
278
279namespace bdlt {
280
281 // ==========
282 // class Date
283 // ==========
284
285/// This class implements a complex-constrained, value-semantic type for
286/// representing dates according to the Unix (POSIX) calendar. Each object of
287/// this class *always* represents a *valid* date value in the range
288/// `[0001JAN01 .. 9999DEC31]` inclusive. The interface of this class supports
289/// `Date` values expressed in terms of either year/month/day (the canonical
290/// representation) or year/day-of-year (an alternate representation). See
291/// @ref bdlt_date-valid-date-values-and-their-representations for details.
292///
293/// See @ref bdlt_date
294class Date {
295 // DATA
296 int d_serialDate; // absolute serial date (1 == 1/1/1, 2 == 1/1/2, ...)
297
298 // FRIENDS
299 friend bool operator==(const Date&, const Date&);
300 friend bool operator!=(const Date&, const Date&);
301 friend bool operator< (const Date&, const Date&);
302 friend bool operator<=(const Date&, const Date&);
303 friend bool operator>=(const Date&, const Date&);
304 friend bool operator> (const Date&, const Date&);
305 friend Date operator+(const Date&, int);
306 friend Date operator+(int, const Date&);
307 friend Date operator-(const Date&, int);
308 friend int operator-(const Date&, const Date&);
309 template <class HASHALG>
310 friend void hashAppend(HASHALG& hashAlg, const Date&);
311
312 private:
313 // PRIVATE CLASS METHODS
314
315 /// Return `true` if the specified `serialDate` represents a valid value
316 /// for a `Date` object, and `false` otherwise. `serialDate` represents a
317 /// valid `Date` value if it corresponds to a valid date as defined by the
318 /// Unix (POSIX) calendar confined to the year range `[1 .. 9999]`
319 /// inclusive, where serial date 1 corresponds to `0001/01/01` and each
320 /// successive day has a serial date value that is 1 greater than that of
321 /// the previous day. See
322 /// [](#Valid Date Values and Their Representations} for details.
323 static bool isValidSerial(int serialDate);
324
325#ifndef BDE_OPENSOURCE_PUBLICATION
326 #ifdef BDE_USE_PROLEPTIC_DATES
327 #error 'BDE_USE_PROLEPTIC_DATES' option disallowed for Bloomberg code.
328 #endif
329#endif
330
331#ifdef BDE_USE_PROLEPTIC_DATES
332 /// Return the serial date in the POSIX calendar having the same
333 /// year-month-day representation as the specified `serialDate`
334 /// represents in the proleptic Gregorian calendar.
335 ///
336 /// \pre The behavior is undefined if `Date` is using a proleptic Gregorian representation
337 /// and `serialDate` has a year-month-day representation earlier than
338 /// 1752/09/14 that is not 0001/01/01.
339 ///
340 /// \note Note that @ref bdlt_date-bdex-compatibility-with-legacy-posix-based-date has further
341 /// details.
342 static int convertProlepticDateToPosix(int serialDate);
343
344 /// Return the serial date in the proleptic Gregorian calendar having
345 /// the same year-month-day representation as the specified `serialDate` represents in the POSIX calendar.
346 ///
347 /// \pre The behavior is undefined if
348 /// `Date` is using a proleptic Gregorian representation and
349 /// `serialDate` has a year-month-day representation earlier than
350 /// 1752/09/14 that is not 0001/01/01.
351 ///
352 /// \note Note that @ref bdlt_date-bdex-compatibility-with-legacy-posix-based-date has further details.
353 static int convertPosixDateToProleptic(int serialDate);
354#endif
355
356 // PRIVATE CREATORS
357
358 /// Create a date initialized with the value indicated by the specified `serialDate`.
359 ///
360 /// \pre The behavior is undefined unless `serialDate` represents
361 /// a valid `Date` value.
362 explicit Date(int serialDate);
363
364 public:
365 // CLASS METHODS
366
367 /// Return `true` if the specified `year` and `dayOfYear` represent a
368 /// valid value for a `Date` object, and `false` otherwise. `year` and
369 /// `dayOfYear` represent a valid `Date` value if they correspond to a
370 /// valid date as defined by the Unix (POSIX) calendar confined to the
371 /// year range `[1 .. 9999]` inclusive. See {Valid Date Values and
372 /// Their Representations} for details.
373 static bool isValidYearDay(int year, int dayOfYear);
374
375 /// Return `true` if the specified `year`, `month`, and `day` represent
376 /// a valid value for a `Date` object, and `false` otherwise. `year`,
377 /// `month`, and `day` represent a valid `Date` value if they correspond
378 /// to a valid date as defined by the Unix (POSIX) calendar confined to
379 /// the year range `[1 .. 9999]` inclusive. See {Valid Date Values and
380 /// Their Representations} for details.
381 static bool isValidYearMonthDay(int year, int month, int day);
382
383 // Aspects
384
385 /// Return the maximum valid BDEX format version, as indicated by the
386 /// specified `versionSelector`, to be passed to the `bdexStreamOut` method.
387 ///
388 /// \note Note that it is highly recommended that `versionSelector`
389 /// be formatted as "YYYYMMDD", a date representation. Also note that
390 /// `versionSelector` should be a *compile*-time-chosen value that
391 /// selects a format version supported by both externalizer and
392 /// unexternalizer. See the `bslx` package-level documentation for more
393 /// information on BDEX streaming of value-semantic types and
394 /// containers.
395 static int maxSupportedBdexVersion(int versionSelector);
396
397 // CREATORS
398
399 /// Create a `Date` object having the earliest supported date value,
400 /// i.e., having a year/month/day representation of `0001/01/01`.
401 Date();
402
403 /// Create a `Date` object having the value represented by the specified `year` and `dayOfYear`.
404 ///
405 /// \pre The behavior is undefined unless `year` and
406 /// `dayOfYear` represent a valid `Date` value (see `isValidYearDay`).
407 Date(int year, int dayOfYear);
408
409 /// Create a `Date` object having the value represented by the specified `year`, `month`, and `day`.
410 ///
411 /// \pre The behavior is undefined unless
412 /// `year`, `month`, and `day` represent a valid `Date` value (see
413 /// `isValidYearMonthDay`).
414 Date(int year, int month, int day);
415
416 /// Create a `Date` object having the value of the specified `original`
417 /// date.
418 Date(const Date& original);
419
420 /// Destroy this object.
421 ~Date();
422
423 // MANIPULATORS
424
425 /// Assign to this object the value of the specified `rhs` date, and
426 /// return a reference providing modifiable access to this object.
427 Date& operator=(const Date& rhs);
428
429 /// Assign to this object the value that is later by the specified
430 /// (signed) `numDays` from its current value, and return a reference
431 /// providing modifiable access to this object.
432 ///
433 /// \pre The behavior is undefined unless the resulting value falls within the range of dates
434 /// supported by this class (see `isValidYearMonthDay`).
435 ///
436 /// \note Note that `numDays` may be negative.
437 Date& operator+=(int numDays);
438
439 /// Assign to this object the value that is earlier by the specified
440 /// (signed) `numDays` from its current value, and return a reference
441 /// providing modifiable access to this object.
442 ///
443 /// \pre The behavior is undefined unless the resulting value falls within the range of dates
444 /// supported by this class (see `isValidYearMonthDay`).
445 ///
446 /// \note Note that `numDays` may be negative.
447 Date& operator-=(int numDays);
448
449 /// Set this object to have the value that is one day later than its
450 /// current value, and return a reference providing modifiable access to this object.
451 ///
452 /// \pre The behavior is undefined if the year/month/day
453 /// representation of the current value is `9999/12/31`.
454 Date& operator++();
455
456 /// Set this object to have the value that is one day earlier than its
457 /// current value, and return a reference providing modifiable access to this object.
458 ///
459 /// \pre The behavior is undefined if the year/month/day
460 /// representation of the current value is `0001/01/01`.
461 Date& operator--();
462
463 /// Set this object to have the value that is later by the specified
464 /// (signed) `numDays` from its current value, if the resulting value
465 /// falls within the range of dates supported by this class (see
466 /// `isValidYearMonthDay`). Return 0 on success, and a non-zero value (with no effect) otherwise.
467 ///
468 /// \note Note that `numDays` may be negative.
469 int addDaysIfValid(int numDays);
470
471 /// Set this object to have the value represented by the specified `year` and `dayOfYear`.
472 ///
473 /// \pre The behavior is undefined unless `year` and
474 /// `dayOfYear` represent a valid `Date` value (see `isValidYearDay`).
475 void setYearDay(int year, int dayOfYear);
476
477 /// Set this object to have the value represented by the specified
478 /// `year` and `dayOfYear` if they comprise a valid `Date` value (see
479 /// `isValidYearDay`). Return 0 on success, and a non-zero value (with
480 /// no effect) otherwise.
481 int setYearDayIfValid(int year, int dayOfYear);
482
483 /// Set this object to have the value represented by the specified `year`, `month`, and `day`.
484 ///
485 /// \pre The behavior is undefined unless
486 /// `year`, `month`, and `day` represent a valid `Date` value (see
487 /// `isValidYearMonthDay`).
488 void setYearMonthDay(int year, int month, int day);
489
490 /// Set this object to have the value represented by the specified
491 /// `year`, `month`, and `day` if they comprise a valid `Date` value
492 /// (see `isValidYearMonthDay`). Return 0 on success, and a non-zero
493 /// value (with no effect) otherwise.
494 int setYearMonthDayIfValid(int year, int month, int day);
495
496 // Aspects
497
498 /// Assign to this object the value read from the specified input
499 /// `stream` using the specified `version` format, and return a
500 /// reference to `stream`. If `stream` is initially invalid, this
501 /// operation has no effect. If `version` is not supported, this object
502 /// is unaltered and `stream` is invalidated, but otherwise unmodified.
503 /// If `version` is supported but `stream` becomes invalid during this
504 /// operation, this object has an undefined, but valid, state.
505 ///
506 /// \note Note that no version is read from `stream`. See the `bslx` package-level
507 /// documentation for more information on BDEX streaming of
508 /// value-semantic types and containers.
509 template <class STREAM>
510 STREAM& bdexStreamIn(STREAM& stream, int version);
511
512 // ACCESSORS
513
514 /// Return the day of the month in the range `[1 .. 31]` of this date.
515 int day() const;
516
517 /// Return the day of the week in the range
518 /// `[DayOfWeek::e_SUN .. DayOfWeek::e_SAT]` of this date.
520
521 /// Return the day of the year in the range `[1 .. 366]` of this date.
522 int dayOfYear() const;
523
524 /// Load, into the specified `year` and `dayOfYear`, the respective
525 /// `year` and `dayOfYear` attribute values of this date.
526 void getYearDay(int *year, int *dayOfYear) const;
527
528 /// Load, into the specified `year`, `month`, and `day`, the respective
529 /// `year`, `month`, and `day` attribute values of this date.
530 void getYearMonthDay(int *year, int *month, int *day) const;
531
532 /// Return the month of the year in the range `[1 .. 12]` of this date.
533 int month() const;
534
535 /// Return the month of the year in the range
536 /// `[MonthOfYear::e_JAN .. MonthOfYear::e_DEC]` of this date.
538
539 /// Return the year in the range `[1 .. 9999]` of this date.
540 int year() const;
541
542 // Aspects
543
544 /// Write the value of this object, using the specified `version`
545 /// format, to the specified output `stream`, and return a reference to
546 /// `stream`. If `stream` is initially invalid, this operation has no
547 /// effect. If `version` is not supported, `stream` is invalidated, but otherwise unmodified.
548 ///
549 /// \note Note that `version` is not written to
550 /// `stream`. See the `bslx` package-level documentation for more
551 /// information on BDEX streaming of value-semantic types and
552 /// containers.
553 template <class STREAM>
554 STREAM& bdexStreamOut(STREAM& stream, int version) const;
555
556 /// Write the value of this object to the specified output `stream` in a
557 /// human-readable format, and return a reference to `stream`.
558 /// Optionally specify an initial indentation `level`, whose absolute
559 /// value is incremented recursively for nested objects. If `level` is
560 /// specified, optionally specify `spacesPerLevel`, whose absolute value
561 /// indicates the number of spaces per indentation level for this and
562 /// all of its nested objects. If `level` is negative, suppress
563 /// indentation of the first line. If `spacesPerLevel` is negative,
564 /// format the entire output on one line, suppressing all but the
565 /// initial indentation (as governed by `level`). If `stream` is not valid on entry, this operation has no effect.
566 ///
567 /// \note Note that this
568 /// human-readable format is not fully specified, and can change without
569 /// notice.
570 bsl::ostream& print(bsl::ostream& stream,
571 int level = 0,
572 int spacesPerLevel = 4) const;
573
574#ifndef BDE_OPENSOURCE_PUBLICATION // pending deprecation
575
576 // DEPRECATED METHODS
577
578 /// Return `true` if the specified `year` and `dayOfYear` represent a
579 /// valid value for a `Date` object, and `false` otherwise. `year` and
580 /// `dayOfYear` represent a valid `Date` value if they correspond to a
581 /// valid date as defined by the Unix (POSIX) calendar confined to the
582 /// year range `[1 .. 9999]` inclusive. See {Valid Date Values and
583 /// Their Representations} for details.
584 ///
585 /// @deprecated Use @ref isValidYearDay instead.
586 static bool isValid(int year, int dayOfYear);
587
588 /// Return `true` if the specified `year`, `month`, and `day` represent
589 /// a valid value for a `Date` object, and `false` otherwise. `year`,
590 /// `month`, and `day` represent a valid `Date` value if they correspond
591 /// to a valid date as defined by the Unix (POSIX) calendar confined to
592 /// the year range `[1 .. 9999]` inclusive. See {Valid Date Values and
593 /// Their Representations} for details.
594 ///
595 /// @deprecated Use @ref isValidYearMonthDay instead.
596 static bool isValid(int year, int month, int day);
597
598 /// Return the most current BDEX streaming version number supported by
599 /// this class.
600 ///
601 /// @deprecated Use @ref maxSupportedBdexVersion(int) instead.
602 static int maxSupportedBdexVersion();
603
604#endif // BDE_OPENSOURCE_PUBLICATION -- pending deprecation
605#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE2.22
606
607 /// Return the most current BDEX streaming version number supported by
608 /// this class.
609 ///
610 /// @deprecated Use @ref maxSupportedBdexVersion(int) instead.
611 static int maxSupportedVersion();
612
613 /// Write the value of this object to the specified output `stream` in a
614 /// single-line format, and return a reference to `stream`. If `stream` is not valid on entry, this operation has no effect.
615 ///
616 /// \note Note that this
617 /// human-readable format is not fully specified, can change without
618 /// notice, and is logically equivalent to:
619 /// @code
620 /// print(stream, 0, -1);
621 /// @endcode
622 ///
623 /// @deprecated Use @ref print instead.
624 bsl::ostream& streamOut(bsl::ostream& stream) const;
625
626 /// Set this object to have the value represented by the specified
627 /// `year` and `dayOfYear` if they comprise a valid `Date` value (see
628 /// `isValidYearDay`). Return 0 on success, and a non-zero value (with
629 /// no effect) otherwise.
630 ///
631 /// @deprecated Use @ref setYearDayIfValid instead.
633
634 /// Set this object to have the value represented by the specified
635 /// `year`, `month`, and `day` if they comprise a valid `Date` value
636 /// (see `isValidYearMonthDay`). Return 0 on success, and a non-zero
637 /// value (with no effect) otherwise.
638 ///
639 /// @deprecated Use @ref setYearMonthDayIfValid instead.
640 int validateAndSetYearMonthDay(int year, int month, int day);
641
642#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE2.22
643};
644
645// FREE OPERATORS
646
647/// Return `true` if the specified `lhs` and `rhs` objects have the same
648/// value, and `false` otherwise. Two `Date` objects have the same value if
649/// each of their `year`, `month`, and `day` attributes (respectively) have
650/// the same value.
651bool operator==(const Date& lhs, const Date& rhs);
652
653/// Return `true` if the specified `lhs` and `rhs` objects do not have the
654/// same value, and `false` otherwise. Two `Date` objects do not have the
655/// same value if any of their `year`, `month`, and `day` attributes
656/// (respectively) do not have the same value.
657bool operator!=(const Date& lhs, const Date& rhs);
658
659/// Write the value of the specified `date` object to the specified output
660/// `stream` in a single-line format, and return a reference to `stream`.
661/// If `stream` is not valid on entry, this operation has no effect.
662///
663/// \note Note that this human-readable format is not fully specified, can change
664/// without notice, and is logically equivalent to:
665/// @code
666/// print(stream, 0, -1);
667/// @endcode
668bsl::ostream& operator<<(bsl::ostream& stream, const Date& date);
669
670/// Return `true` if the specified `lhs` date is earlier than the specified
671/// `rhs` date, and `false` otherwise.
672bool operator<(const Date& lhs, const Date& rhs);
673
674/// Return `true` if the specified `lhs` date is earlier than or the same as
675/// the specified `rhs` date, and `false` otherwise.
676bool operator<=(const Date& lhs, const Date& rhs);
677
678/// Return `true` if the specified `lhs` date is later than the specified
679/// `rhs` date, and `false` otherwise.
680bool operator>(const Date& lhs, const Date& rhs);
681
682/// Return `true` if the specified `lhs` date is later than or the same as
683/// the specified `rhs` date, and `false` otherwise.
684bool operator>=(const Date& lhs, const Date& rhs);
685
686/// Set the specified `date` object to have the value that is one day later
687/// than its current value, and return the value of `date` on entry.
688///
689/// \pre The behavior is undefined if the value of `date` on entry is `9999/12/31`.
690Date operator++(Date& date, int);
691
692/// Set the specified `date` object to have the value that is one day
693/// earlier than its current value, and return the value of `date` on entry.
694///
695/// \pre The behavior is undefined if the value of `date` on entry is
696/// `0001/01/01`.
697Date operator--(Date& date, int);
698
699/// Return the date value that is later by the specified (signed) `numDays` from the specified `date`.
700///
701/// \pre The behavior is undefined unless the
702/// resulting value falls within the range of dates supported by this class (see `isValidYearMonthDay`).
703///
704/// \note Note that `numDays` may be negative.
705Date operator+(const Date& date, int numDays);
706Date operator+(int numDays, const Date& date);
707
708/// Return the date value that is earlier by the specified (signed) `numDays` from the specified `date`.
709///
710/// \pre The behavior is undefined unless
711/// the resulting value falls within the range of dates supported by this class (see `isValidYearMonthDay`).
712///
713/// \note Note that `numDays` may be negative.
714Date operator-(const Date& date, int numDays);
715
716/// Return the (signed) number of days between the specified `lhs` and `rhs` dates.
717///
718/// \note Note that if `lhs < rhs` the result will be negative.
719int operator-(const Date& lhs, const Date& rhs);
720
721// FREE FUNCTIONS
722
723/// Pass the specified `object` to the specified `hashAlg`. This function
724/// integrates with the `bslh` modular hashing system and effectively
725/// provides a `bsl::hash` specialization for `Date`.
726template <class HASHALG>
727void hashAppend(HASHALG& hashAlg, const Date& object);
728
729// ============================================================================
730// INLINE DEFINITIONS
731// ============================================================================
732
733 // ----------
734 // class Date
735 // ----------
736
737// PRIVATE CLASS METHODS
738inline
739bool Date::isValidSerial(int serialDate)
740{
741 return SerialDateImpUtil::isValidSerial(serialDate);
742}
743
744
745#ifdef BDE_USE_PROLEPTIC_DATES
746inline
747int Date::convertProlepticDateToPosix(int serialDate)
748{
749 if (1 != serialDate) { // Preserve the default value.
750
751 serialDate += 2; // Ensure that serial values for 1752SEP14 and later
752 // dates "align".
753 }
754 return serialDate;
755}
756
757inline
758int Date::convertPosixDateToProleptic(int serialDate)
759{
760 if (serialDate > 3) {
761 serialDate -= 2; // ensure that serial values for 1752SEP14
762 // and later dates "align"
763 }
764 else if (serialDate > 0) {
765 serialDate = 1; // "fuzzy" default value '[1 .. 3]'
766 }
767 return serialDate;
768}
769#endif
770
771// PRIVATE CREATORS
772inline
773Date::Date(int serialDate)
774: d_serialDate(serialDate)
775{
776 BSLS_REVIEW(Date::isValidSerial(d_serialDate));
777}
778
779// CLASS METHODS
780inline
781bool Date::isValidYearDay(int year, int dayOfYear)
782{
783 return SerialDateImpUtil::isValidYearDay(year, dayOfYear);
784}
785
786inline
787bool Date::isValidYearMonthDay(int year, int month, int day)
788{
789 return SerialDateImpUtil::isValidYearMonthDay(year, month, day);
790}
791
792 // Aspects
793
794inline
795int Date::maxSupportedBdexVersion(int /* versionSelector */)
796{
797 return 1;
798}
799
800// CREATORS
801inline
802Date::Date()
803: d_serialDate(1)
804{
805}
806
807inline
808Date::Date(int year, int dayOfYear)
809: d_serialDate(SerialDateImpUtil::ydToSerial(year, dayOfYear))
810{
812}
813
814inline
815Date::Date(int year, int month, int day)
816: d_serialDate(SerialDateImpUtil::ymdToSerial(year, month, day))
817{
819}
820
821inline
822Date::Date(const Date& original)
823: d_serialDate(original.d_serialDate)
824{
825}
826
827inline
829{
830 BSLS_REVIEW(Date::isValidSerial(d_serialDate));
831}
832
833// MANIPULATORS
834inline
836{
837 d_serialDate = rhs.d_serialDate;
838 return *this;
839}
840
841inline
843{
844 BSLS_REVIEW(Date::isValidSerial(d_serialDate + numDays));
845
846 d_serialDate += numDays;
847 return *this;
848}
849
850inline
852{
853 BSLS_REVIEW(Date::isValidSerial(d_serialDate - numDays));
854
855 d_serialDate -= numDays;
856 return *this;
857}
858
859inline
861{
862 BSLS_REVIEW(*this != Date(9999, 12, 31));
863
864 ++d_serialDate;
865 return *this;
866}
867
868inline
870{
871 BSLS_REVIEW(*this != Date(1, 1, 1));
872
873 --d_serialDate;
874 return *this;
875}
876
877inline
878void Date::setYearDay(int year, int dayOfYear)
879{
881
883}
884
885inline
886int Date::setYearDayIfValid(int year, int dayOfYear)
887{
888 enum { k_SUCCESS = 0, k_FAILURE = -1 };
889
892 return k_SUCCESS; // RETURN
893 }
894
895 return k_FAILURE;
896}
897
898inline
899void Date::setYearMonthDay(int year, int month, int day)
900{
904
906}
907
908inline
909int Date::setYearMonthDayIfValid(int year, int month, int day)
910{
911 enum { k_SUCCESS = 0, k_FAILURE = -1 };
912
915 return k_SUCCESS; // RETURN
916 }
917
918 return k_FAILURE;
919}
920
921 // Aspects
922
923template <class STREAM>
924STREAM& Date::bdexStreamIn(STREAM& stream, int version)
925{
926 if (stream) {
927 switch (version) { // switch on the schema version
928 case 1: {
929 int tmpSerialDate = 0;
930
931 stream.getInt24(tmpSerialDate);
932
933#ifdef BDE_USE_PROLEPTIC_DATES
934 tmpSerialDate = convertPosixDateToProleptic(tmpSerialDate);
935#endif
936
937 if (stream && Date::isValidSerial(tmpSerialDate)) {
938 d_serialDate = tmpSerialDate;
939 }
940 else {
941 stream.invalidate();
942 }
943 } break;
944 default: {
945 stream.invalidate(); // unrecognized version number
946 }
947 }
948 }
949
950 return stream;
951}
952
953// ACCESSORS
954inline
955int Date::day() const
956{
957 return SerialDateImpUtil::serialToDay(d_serialDate);
958}
959
960inline
962{
963 return static_cast<DayOfWeek::Enum>(
965}
966
967inline
969{
970 return SerialDateImpUtil::serialToDayOfYear(d_serialDate);
971}
972
973inline
974void Date::getYearDay(int *year, int *dayOfYear) const
975{
978
980}
981
982inline
983void Date::getYearMonthDay(int *year, int *month, int *day) const
984{
988
990}
991
992inline
993int Date::month() const
994{
995 return SerialDateImpUtil::serialToMonth(d_serialDate);
996}
997
998inline
1000{
1001 return static_cast<MonthOfYear::Enum>(month());
1002}
1003
1004inline
1005int Date::year() const
1006{
1007 return SerialDateImpUtil::serialToYear(d_serialDate);
1008}
1009
1010 // Aspects
1011
1012template <class STREAM>
1013STREAM& Date::bdexStreamOut(STREAM& stream, int version) const
1014{
1015 if (stream) {
1016 switch (version) { // switch on the schema version
1017 case 1: {
1018#ifndef BDE_OPENSOURCE_PUBLICATION // pending deprecation
1019 // Prevent a corrupt date value from escaping the process (whereby
1020 // it may contaminate a database, for example).
1021
1022 BSLS_ASSERT_OPT(Date::isValidSerial(d_serialDate));
1023#endif // BDE_OPENSOURCE_PUBLICATION -- pending deprecation
1024
1025#ifdef BDE_USE_PROLEPTIC_DATES
1026 stream.putInt24(convertProlepticDateToPosix(d_serialDate));
1027#else
1028 stream.putInt24(d_serialDate);
1029#endif
1030
1031 } break;
1032 default: {
1033 stream.invalidate(); // unrecognized version number
1034 }
1035 }
1036 }
1037 return stream;
1038}
1039
1040#ifndef BDE_OPENSOURCE_PUBLICATION // pending deprecation
1041
1042// DEPRECATED METHODS
1043inline
1044bool Date::isValid(int year, int dayOfYear)
1045{
1046 return isValidYearDay(year, dayOfYear);
1047}
1048
1049inline
1050bool Date::isValid(int year, int month, int day)
1051{
1053}
1054
1055inline
1060
1061#endif // BDE_OPENSOURCE_PUBLICATION -- pending deprecation
1062#ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE2.22
1063inline
1065{
1066 return maxSupportedBdexVersion(0);
1067}
1068
1069inline
1070bsl::ostream& Date::streamOut(bsl::ostream& stream) const
1071{
1072 return print(stream, 0, -1);
1073}
1074
1075inline
1076int Date::validateAndSetYearDay(int year, int dayOfYear)
1077{
1079}
1080
1081inline
1082int Date::validateAndSetYearMonthDay(int year, int month, int day)
1083{
1085}
1086
1087#endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE2.22
1088
1089} // close package namespace
1090
1091// FREE OPERATORS
1092inline
1093bool bdlt::operator==(const Date& lhs, const Date& rhs)
1094{
1095 return lhs.d_serialDate == rhs.d_serialDate;
1096}
1097
1098inline
1099bool bdlt::operator!=(const Date& lhs, const Date& rhs)
1100{
1101 return lhs.d_serialDate != rhs.d_serialDate;
1102}
1103
1104inline
1105bsl::ostream& bdlt::operator<<(bsl::ostream& stream, const Date& date)
1106{
1107 return date.print(stream, 0, -1);
1108}
1109
1110inline
1111bool bdlt::operator<(const Date& lhs, const Date& rhs)
1112{
1113 return lhs.d_serialDate < rhs.d_serialDate;
1114}
1115
1116inline
1117bool bdlt::operator<=(const Date& lhs, const Date& rhs)
1118{
1119 return lhs.d_serialDate <= rhs.d_serialDate;
1120}
1121
1122inline
1123bool bdlt::operator>(const Date& lhs, const Date& rhs)
1124{
1125 return lhs.d_serialDate > rhs.d_serialDate;
1126}
1127
1128inline
1129bool bdlt::operator>=(const Date& lhs, const Date& rhs)
1130{
1131 return lhs.d_serialDate >= rhs.d_serialDate;
1132}
1133
1134inline
1135bdlt::Date bdlt::operator++(Date& date, int)
1136{
1137 BSLS_REVIEW(date != Date(9999, 12, 31));
1138
1139 Date tmp(date);
1140 ++date;
1141 return tmp;
1142}
1143
1144inline
1145bdlt::Date bdlt::operator--(Date& date, int)
1146{
1147 BSLS_REVIEW(date != Date(1, 1, 1));
1148
1149 Date tmp(date);
1150 --date;
1151 return tmp;
1152}
1153
1154inline
1155bdlt::Date bdlt::operator+(const Date& date, int numDays)
1156{
1157 BSLS_REVIEW(Date::isValidSerial(date.d_serialDate + numDays));
1158
1159 return Date(date.d_serialDate + numDays);
1160}
1161
1162inline
1163bdlt::Date bdlt::operator+(int numDays, const Date& date)
1164{
1165 BSLS_REVIEW(Date::isValidSerial(numDays + date.d_serialDate));
1166
1167 return Date(numDays + date.d_serialDate);
1168}
1169
1170inline
1171bdlt::Date bdlt::operator-(const Date& date, int numDays)
1172{
1173 BSLS_REVIEW(Date::isValidSerial(date.d_serialDate - numDays));
1174
1175 return Date(date.d_serialDate - numDays);
1176}
1177
1178inline
1179int bdlt::operator-(const Date& lhs, const Date& rhs)
1180{
1181 return lhs.d_serialDate - rhs.d_serialDate;
1182}
1183
1184// FREE FUNCTIONS
1185template <class HASHALG>
1186inline
1187void bdlt::hashAppend(HASHALG& hashAlg, const Date& object)
1188{
1189 using ::BloombergLP::bslh::hashAppend;
1190 hashAppend(hashAlg, object.d_serialDate);
1191}
1192
1193namespace bslmf {
1194
1195/// This template specialization for `IsBitwiseCopyable` indicates that
1196/// `Date` is a bitwise copyable type.
1197template <>
1199};
1200
1201} // close namespace bslmf
1202
1203
1204
1205#endif
1206
1207// ----------------------------------------------------------------------------
1208// Copyright 2014 Bloomberg Finance L.P.
1209//
1210// Licensed under the Apache License, Version 2.0 (the "License");
1211// you may not use this file except in compliance with the License.
1212// You may obtain a copy of the License at
1213//
1214// http://www.apache.org/licenses/LICENSE-2.0
1215//
1216// Unless required by applicable law or agreed to in writing, software
1217// distributed under the License is distributed on an "AS IS" BASIS,
1218// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1219// See the License for the specific language governing permissions and
1220// limitations under the License.
1221// ----------------------------- END-OF-FILE ----------------------------------
1222
1223/** @} */
1224/** @} */
1225/** @} */
Definition bdlt_date.h:294
void setYearDay(int year, int dayOfYear)
Definition bdlt_date.h:878
friend bool operator>=(const Date &, const Date &)
friend bool operator>(const Date &, const Date &)
void getYearMonthDay(int *year, int *month, int *day) const
Definition bdlt_date.h:983
friend Date operator-(const Date &, int)
bsl::ostream & streamOut(bsl::ostream &stream) const
Definition bdlt_date.h:1070
~Date()
Destroy this object.
Definition bdlt_date.h:828
static int maxSupportedBdexVersion()
Definition bdlt_date.h:1056
friend int operator-(const Date &, const Date &)
int dayOfYear() const
Return the day of the year in the range [1 .. 366] of this date.
Definition bdlt_date.h:968
static bool isValid(int year, int dayOfYear)
Definition bdlt_date.h:1044
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
static bool isValidYearDay(int year, int dayOfYear)
Definition bdlt_date.h:781
friend void hashAppend(HASHALG &hashAlg, const Date &)
int day() const
Return the day of the month in the range [1 .. 31] of this date.
Definition bdlt_date.h:955
int setYearMonthDayIfValid(int year, int month, int day)
Definition bdlt_date.h:909
void setYearMonthDay(int year, int month, int day)
Definition bdlt_date.h:899
int validateAndSetYearDay(int year, int dayOfYear)
Definition bdlt_date.h:1076
Date & operator--()
Definition bdlt_date.h:869
int addDaysIfValid(int numDays)
Date & operator++()
Definition bdlt_date.h:860
Date & operator=(const Date &rhs)
Definition bdlt_date.h:835
static int maxSupportedVersion()
Definition bdlt_date.h:1064
MonthOfYear::Enum monthOfYear() const
Definition bdlt_date.h:999
int year() const
Return the year in the range [1 .. 9999] of this date.
Definition bdlt_date.h:1005
static bool isValidYearMonthDay(int year, int month, int day)
Definition bdlt_date.h:787
friend bool operator!=(const Date &, const Date &)
STREAM & bdexStreamOut(STREAM &stream, int version) const
Definition bdlt_date.h:1013
int validateAndSetYearMonthDay(int year, int month, int day)
Definition bdlt_date.h:1082
friend Date operator+(const Date &, int)
Date & operator-=(int numDays)
Definition bdlt_date.h:851
Date()
Definition bdlt_date.h:802
int month() const
Return the month of the year in the range [1 .. 12] of this date.
Definition bdlt_date.h:993
int setYearDayIfValid(int year, int dayOfYear)
Definition bdlt_date.h:886
friend bool operator<(const Date &, const Date &)
friend bool operator==(const Date &, const Date &)
Date & operator+=(int numDays)
Definition bdlt_date.h:842
friend Date operator+(int, const Date &)
void getYearDay(int *year, int *dayOfYear) const
Definition bdlt_date.h:974
friend bool operator<=(const Date &, const Date &)
DayOfWeek::Enum dayOfWeek() const
Definition bdlt_date.h:961
STREAM & bdexStreamIn(STREAM &stream, int version)
Definition bdlt_date.h:924
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:2045
#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(X)
Definition bsls_review.h:1019
void hashAppend(HASH_ALGORITHM &hashAlgorithm, const BigEndianInt16 &object)
Definition bbldc_basicisma30360.h:112
bool operator>(const Date &lhs, const Date &rhs)
bool operator<(const Date &lhs, const Date &rhs)
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)
bool operator>=(const Date &lhs, const Date &rhs)
Date operator+(const Date &date, int numDays)
bsl::ostream & operator<<(bsl::ostream &stream, const Calendar &calendar)
bool operator<=(const Date &lhs, const Date &rhs)
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 bdlbb_blob.h:579
Enum
Enumerated day-of-week values.
Definition bdlt_dayofweek.h:125
Enum
Define the list of month-of-year values.
Definition bdlt_monthofyear.h:138
Definition bdlt_posixdateimputil.h:528
static bool isValidSerial(int serialDay)
Definition bdlt_posixdateimputil.h:800
static void serialToYmd(int *year, int *month, int *day, int serialDay)
static int serialToYear(int serialDay)
static int serialToMonth(int serialDay)
static int ymdToSerial(int year, int month, int day)
static int serialToDay(int serialDay)
static int ydToSerial(int year, int dayOfYear)
static int serialToDayOfWeek(int serialDay)
static void serialToYd(int *year, int *dayOfYear, int serialDay)
static int serialToDayOfYear(int serialDay)
Definition bdlt_posixdateimputil.h:808
Definition bslmf_isbitwisecopyable.h:298