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