BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlt_posixdateimputil.h
Go to the documentation of this file.
1/// @file bdlt_posixdateimputil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlt_posixdateimputil.h -*-C++-*-
8#ifndef INCLUDED_BDLT_POSIXDATEIMPUTIL
9#define INCLUDED_BDLT_POSIXDATEIMPUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlt_posixdateimputil bdlt_posixdateimputil
15/// @brief Provide low-level support functions for date-value manipulation.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlt
19/// @{
20/// @addtogroup bdlt_posixdateimputil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlt_posixdateimputil-purpose"> Purpose</a>
25/// * <a href="#bdlt_posixdateimputil-classes"> Classes </a>
26/// * <a href="#bdlt_posixdateimputil-description"> Description </a>
27/// * <a href="#bdlt_posixdateimputil-representations-valid-dates-and-leap-years"> Representations, Valid Dates, and Leap Years </a>
28/// * <a href="#bdlt_posixdateimputil-caching"> Caching </a>
29/// * <a href="#bdlt_posixdateimputil-usage"> Usage </a>
30/// * <a href="#bdlt_posixdateimputil-creating-a-general-purpose-utility"> Creating a General Purpose Utility </a>
31/// * <a href="#bdlt_posixdateimputil-implementing-a-value-semantic-date-type"> Implementing a Value-Semantic Date Type </a>
32///
33/// # Purpose {#bdlt_posixdateimputil-purpose}
34/// Provide low-level support functions for date-value manipulation.
35///
36/// # Classes {#bdlt_posixdateimputil-classes}
37///
38/// - bdlt::PosixDateImpUtil: suite of low-level date-related stateless functions
39///
40/// # Description {#bdlt_posixdateimputil-description}
41/// This component implements a utility class,
42/// `bdlt::PosixDateImpUtil`, that provides a suite of low-level, date-related
43/// functions that can be used to validate, manipulate, and convert among values
44/// in three different formats:
45/// @code
46/// YMD: year/month/day
47/// YD: year/dayOfYear
48/// S: serialDate
49/// @endcode
50/// The supplied functionality can also be used for determining leap years,
51/// finding the last day in a month, and for determining the day of the week for
52/// a given date. Note that in this component, a "date" is understood to
53/// represent a valid day in the range `0001JAN01` to `9999DEC31`, according to
54/// the standard UNIX date implementation.
55///
56/// ## Representations, Valid Dates, and Leap Years {#bdlt_posixdateimputil-representations-valid-dates-and-leap-years}
57///
58///
59/// The "Calendar Date", or "year-month-day (ymd)", is the primary
60/// representation and is denoted as "yyyy/mm/dd", with valid years being in the
61/// range `[ 1 .. 9999 ]`. Within a valid year, valid months and valid days are
62/// confined to the respective ranges `[ 1 .. 12 ]` and `[ 1 .. 31 ]`. Valid
63/// dates in this representation will range from `0001/01/01` to `9999/12/31`,
64/// but are also governed by the standard UNIX (Gregorian) calendar convention.
65///
66/// The "Day-Of-Year Date", or "year-day (yd)" representation, denoted by
67/// "yyyy/ddd", represents dates by their year, again in the range
68/// `[ 1 .. 9999 ]`, and the day of year, in the range `[ 1 .. 366 ]`. Note
69/// that valid date values in this representation range from `0001/01` to
70/// `9999/365`, with a day-of-year value of 366 permitted for leap years only.
71///
72/// The "Serial Date" representation depicts dates as consecutive integers,
73/// beginning with 1 (representing `0001JAN01`). In this representation, valid
74/// date value are in the range `[ 1 .. 3652061 ]`.
75///
76/// In a leap year, February has 29 days instead of the usual 28. For years
77/// subsequent to 1752, a year is a leap year if it is divisible by 4, but not
78/// divisible by 100, unless it is also divisible by 400. Prior to 1752, all
79/// years divisible by 4 were leap years. Note that the year 1752 had only
80/// `366 - 11 = 355` days, as September 3rd through the 13th were omitted (in a
81/// one-time correction to the previous, less accurate, leap-year convention).
82///
83/// ## Caching {#bdlt_posixdateimputil-caching}
84///
85///
86/// To achieve maximal runtime performance, several of the functions in this
87/// component reserve the right to be implemented using statically cached (i.e.,
88/// tabulated) values (which is inherently thread-safe). In all cases where a
89/// cache may be used, `bdlt::PosixDateImpUtil` explicitly provides a `NoCache`
90/// version (e.g., `ymdToSerialNoCache`) that is guaranteed NOT to use a cache.
91/// Although the "normal" (potentially cached) functions typically gain huge
92/// performance advantages, the `NoCache` versions may conceivably be preferred
93/// by the performance-minded user who is *reasonably* *certain* that the vast
94/// majority of date values of interest will miss the cache (thus incurring a
95/// small, but unnecessary overhead for the cache-hit tests). Note, however,
96/// that the `NoCache` function variants are provided primarily for testing and
97/// for generating that cache in the first place (see
98/// `bdlt_posixdateimputil.t.cpp`).
99///
100/// ## Usage {#bdlt_posixdateimputil-usage}
101///
102///
103/// This component was created primarily to support the implementation of a
104/// general-purpose, value-semantic (vocabulary) "Date" type, but also provides
105/// many low-level utility functions suitable for direct use by other clients.
106///
107/// ### Creating a General Purpose Utility {#bdlt_posixdateimputil-creating-a-general-purpose-utility}
108///
109///
110/// Many of the functions provided by this component can be used directly by
111/// clients that want to ask questions about a particular date in one of the
112/// three supported formats.
113///
114/// What day of the week was January 3, 2010?
115/// @code
116/// assert(2 == bdlt::PosixDateImpUtil::ymdToDayOfWeek(2010, 3, 1));
117/// // 2 means Monday.
118/// @endcode
119/// Was the year 2000 a leap year?
120/// @code
121/// assert(true == bdlt::PosixDateImpUtil::isLeapYear(2000));
122/// // Yes, it was.
123/// @endcode
124/// Was February 29, 1900, a valid date in history?
125/// @code
126/// assert(false == bdlt::PosixDateImpUtil::isValidYearMonthDay(1900, 2, 29));
127/// // No, it was not.
128/// @endcode
129/// What was the last day of February in 1600?
130/// @code
131/// assert(29 == bdlt::PosixDateImpUtil::lastDayOfMonth(1600, 2));
132/// // The 29th.
133/// @endcode
134/// How many leap years occur from 1959 to 2012 inclusive?
135/// @code
136/// assert(14 == bdlt::PosixDateImpUtil::numLeapYears(1959, 2012));
137/// // There are 14.
138/// @endcode
139/// On what day of the year does February 29, 2020 fall?
140/// @code
141/// assert(60 == bdlt::PosixDateImpUtil::ymdToDayOfYear(2020, 2, 29));
142/// // The 60th one.
143/// @endcode
144/// In what month does the 120th day of 2011 fall?
145/// @code
146/// assert(4 == bdlt::PosixDateImpUtil::ydToMonth(2011, 120));
147/// // 4 means April.
148/// @endcode
149///
150/// ### Implementing a Value-Semantic Date Type {#bdlt_posixdateimputil-implementing-a-value-semantic-date-type}
151///
152///
153/// Using the functions supplied in this component, we can easily implement a
154/// C++ class that represents abstract (*mathematical*) date values and performs
155/// a few common operations on them. The internal representation could be any
156/// of the three supported by this component; in this example, we will choose to
157/// represent the date value internally as a "serial date":
158/// @code
159/// /// This class represents a valid date in the range
160/// /// `[ 0001/01/01 .. 9999/12/31 ]`.
161/// class MyDate {
162///
163/// // DATA
164/// int d_serialDate; // 1 = 0001JAN01, 2 = 0001JAN02, ...
165///
166/// // FRIENDS
167/// friend MyDate operator+(const MyDate&, int);
168/// friend MyDate operator+(int, const MyDate&);
169/// friend int operator- (const MyDate&, const MyDate&);
170/// friend bool operator==(const MyDate&, const MyDate&);
171///
172/// private:
173/// // PRIVATE CREATORS
174/// explicit MyDate(int serialDate);
175/// @endcode
176/// Next we define the public interface of the class, with function-level
177/// documentation conspicuously omitted (note, however, that reference
178/// implementations with preconditions asserted will follow):
179/// @code
180/// public:
181/// // TYPES
182/// enum Day {
183/// SUN = 1,
184/// MON = 2,
185/// TUE = 3,
186/// WED = 4,
187/// THU = 5,
188/// FRI = 6,
189/// SAT = 7
190/// };
191///
192/// // CLASS METHODS
193/// static bool isValid(int year, int month, int day);
194///
195/// // CREATORS
196/// MyDate();
197/// MyDate(const MyDate& original);
198/// ~MyDate();
199///
200/// // MANIPULATORS
201/// MyDate& operator=(const MyDate& rhs);
202/// MyDate& operator++();
203/// MyDate& operator--();
204/// MyDate& operator+=(int numDays);
205/// MyDate& operator-=(int numDays);
206/// void setYearMonthDay(int year, int month, int day);
207/// bool setYearMonthDayIfValid(int year, int month, int day);
208///
209/// // ACCESSORS
210/// void getYearMonthDay(int *year, int *month, int *day) const;
211/// int year() const;
212/// int month() const;
213/// int day() const;
214/// Day dayOfWeek() const;
215/// bool isLeapYear() const;
216/// bsl::ostream& print(bsl::ostream& stream) const;
217/// };
218///
219/// // FREE OPERATORS
220/// bool operator==(const MyDate& lhs, const MyDate& rhs);
221/// bool operator!=(const MyDate& lhs, const MyDate& rhs);
222///
223/// bsl::ostream& operator<<(bsl::ostream& stream, const MyDate& rhs);
224///
225/// MyDate operator+(const MyDate& lhs, int rhs);
226/// MyDate operator+(int lhs, const MyDate& rhs);
227///
228/// int operator-(const MyDate& lhs, const MyDate& rhs);
229///
230/// MyDate operator++(MyDate& object, int);
231/// MyDate operator--(MyDate& object, int);
232/// @endcode
233/// We now provide a reference implementation of each of the methods and free
234/// (operator) functions associated with the `MyDate` class defined above (using
235/// @ref bsls_assert to identify preconditions and invariants where appropriate):
236/// @code
237/// // PRIVATE CREATORS
238/// inline
239/// MyDate::MyDate(int serialDate)
240/// : d_serialDate(serialDate)
241/// {
242/// }
243///
244/// // CLASS METHODS
245/// inline
246/// bool MyDate::isValid(int year, int month, int day)
247/// {
248/// return bdlt::PosixDateImpUtil::isValidYearMonthDay(year, month, day);
249/// }
250///
251/// // CREATORS
252/// inline
253/// MyDate::MyDate()
254/// : d_serialDate(1)
255/// {
256/// }
257///
258/// inline
259/// MyDate::MyDate(const MyDate& original)
260/// : d_serialDate(original.d_serialDate)
261/// {
262/// }
263///
264/// inline
265/// MyDate::~MyDate()
266/// {
267/// }
268///
269/// // MANIPULATORS
270/// inline
271/// MyDate& MyDate::operator=(const MyDate& rhs)
272/// {
273/// d_serialDate = rhs.d_serialDate;
274/// return *this;
275/// }
276///
277/// inline
278/// MyDate& MyDate::operator++()
279/// {
280/// ++d_serialDate;
281/// BSLS_ASSERT_SAFE(bdlt::PosixDateImpUtil::isValidSerial(d_serialDate));
282/// return *this;
283/// }
284///
285/// inline
286/// MyDate& MyDate::operator--()
287/// {
288/// --d_serialDate;
289/// BSLS_ASSERT_SAFE(bdlt::PosixDateImpUtil::isValidSerial(d_serialDate));
290/// return *this;
291/// }
292///
293/// inline
294/// MyDate& MyDate::operator+=(int numDays)
295/// {
296/// d_serialDate += numDays;
297/// BSLS_ASSERT_SAFE(bdlt::PosixDateImpUtil::isValidSerial(d_serialDate));
298/// return *this;
299/// }
300///
301/// inline
302/// MyDate& MyDate::operator-=(int numDays)
303/// {
304/// d_serialDate -= numDays;
305/// BSLS_ASSERT_SAFE(bdlt::PosixDateImpUtil::isValidSerial(d_serialDate));
306/// return *this;
307/// }
308///
309/// inline
310/// void MyDate::setYearMonthDay(int year, int month, int day)
311/// {
312/// d_serialDate = bdlt::PosixDateImpUtil::ymdToSerial(year, month, day);
313/// BSLS_ASSERT_SAFE(bdlt::PosixDateImpUtil::isValidSerial(d_serialDate));
314/// }
315///
316/// inline
317/// bool MyDate::setYearMonthDayIfValid(int year, int month, int day)
318/// {
319/// const int newDate = bdlt::PosixDateImpUtil::ymdToSerial(year,
320/// month,
321/// day);
322/// if (bdlt::PosixDateImpUtil::isValidSerial(newDate)) {
323/// d_serialDate = newDate;
324/// return true; // RETURN
325/// }
326/// return false;
327/// }
328///
329/// // ACCESSORS
330/// inline
331/// void MyDate::getYearMonthDay(int *year, int *month, int *day) const
332/// {
333/// bdlt::PosixDateImpUtil::serialToYmd(year, month, day, d_serialDate);
334/// }
335///
336/// inline
337/// int MyDate::year() const
338/// {
339/// return bdlt::PosixDateImpUtil::serialToYear(d_serialDate);
340/// }
341///
342/// inline
343/// int MyDate::month() const
344/// {
345/// return bdlt::PosixDateImpUtil::serialToMonth(d_serialDate);
346/// }
347///
348/// inline
349/// int MyDate::day() const
350/// {
351/// return bdlt::PosixDateImpUtil::serialToDay(d_serialDate);
352/// }
353///
354/// inline
355/// MyDate::Day MyDate::dayOfWeek() const
356/// {
357/// return MyDate::Day(bdlt::PosixDateImpUtil::serialToDayOfWeek(
358/// d_serialDate));
359/// }
360///
361/// inline
362/// bool MyDate::isLeapYear() const
363/// {
364/// return bdlt::PosixDateImpUtil::isLeapYear(year());
365/// }
366///
367/// // FREE OPERATORS
368/// inline
369/// bool operator==(const MyDate& lhs, const MyDate& rhs)
370/// {
371/// return lhs.d_serialDate == rhs.d_serialDate;
372/// }
373///
374/// inline
375/// bool operator!=(const MyDate& lhs, const MyDate& rhs)
376/// {
377/// return !(lhs == rhs);
378/// }
379///
380/// inline
381/// bsl::ostream& operator<<(bsl::ostream& stream, const MyDate& rhs)
382/// {
383/// return rhs.print(stream);
384/// }
385///
386/// inline
387/// MyDate operator+(const MyDate& lhs, int rhs)
388/// {
389/// return MyDate(lhs.d_serialDate + rhs);
390/// }
391///
392/// inline
393/// MyDate operator+(int lhs, const MyDate& rhs)
394/// {
395/// return MyDate(lhs + rhs.d_serialDate);
396/// }
397///
398/// inline
399/// int operator-(const MyDate& lhs, const MyDate& rhs)
400/// {
401/// return lhs.d_serialDate - rhs.d_serialDate;
402/// }
403///
404/// inline
405/// MyDate operator++(MyDate& object, int)
406/// {
407/// MyDate tmp(object);
408/// ++object;
409/// return tmp;
410/// }
411///
412/// inline
413/// MyDate operator--(MyDate& object, int)
414/// {
415/// MyDate tmp(object);
416/// --object;
417/// return tmp;
418/// }
419/// @endcode
420/// The following definitions would appropriately appear in the implementation
421/// (`.cpp`) file:
422/// @code
423/// const char *const monthNames[] = {
424/// 0, "JAN", "FEB", "MAR", "APR",
425/// "MAY", "JUN", "JUL", "AUG",
426/// "SEP", "OCT", "NOV", "DEC"
427/// };
428///
429/// // MANIPULATORS
430/// bsl::ostream& MyDate::print(bsl::ostream& stream) const
431/// {
432/// if (!stream) {
433/// return stream; // RETURN
434/// }
435///
436/// // space usage: ddMMMyyyy null
437/// const int SIZE = 2 + 3 + 4 + 1;
438/// char buf[SIZE];
439///
440/// int y, m, d;
441/// bdlt::PosixDateImpUtil::serialToYmd(&y, &m, &d, d_serialDate);
442///
443/// buf[0] = d / 10 + '0';
444/// buf[1] = d % 10 + '0';
445///
446/// bsl::memcpy(&buf[2], monthNames[m], 3);
447///
448/// buf[5] = y / 1000 + '0';
449/// buf[6] = ((y % 1000) / 100) + '0';
450/// buf[7] = ((y % 100) / 10) + '0';
451/// buf[8] = y % 10 + '0';
452/// buf[9] = 0;
453///
454/// stream << buf;
455///
456/// return stream;
457/// }
458/// @endcode
459/// The following snippets of code illustrate how to create and use a `Mydate`
460/// object. First create a default object, `d1`:
461/// @code
462/// MyDate d1; assert( 1 == d1.year());
463/// assert( 1 == d1.month());
464/// assert( 1 == d1.day());
465/// @endcode
466/// Next, set `d1` to July 4, 1776:
467/// @code
468/// d1.setYearMonthDay(1776, 7, 4); assert(1776 == d1.year());
469/// assert( 7 == d1.month());
470/// assert( 4 == d1.day());
471/// @endcode
472/// Then create `d2` as a copy of `d1`:
473/// @code
474/// MyDate d2(d1); assert(1776 == d2.year());
475/// assert( 7 == d2.month());
476/// assert( 4 == d2.day());
477/// @endcode
478/// Now, add six days to the value of `d2`:
479/// @code
480/// d2 += 6; assert(1776 == d2.year());
481/// assert( 7 == d2.month());
482/// assert( 10 == d2.day());
483/// @endcode
484/// Next subtract `d1` from `d2`, storing the difference (in days) in `dDays`:
485/// @code
486/// int dDays = d2 - d1; assert(6 == dDays);
487/// @endcode
488/// Finally, stream the value of `d2` to `stdout`:
489/// @code
490/// bsl::cout << d2 << bsl::endl;
491/// @endcode
492/// The streaming operator produces the following output on `stdout`:
493/// @code
494/// 10JUL1776
495/// @endcode
496/// @}
497/** @} */
498/** @} */
499
500/** @addtogroup bdl
501 * @{
502 */
503/** @addtogroup bdlt
504 * @{
505 */
506/** @addtogroup bdlt_posixdateimputil
507 * @{
508 */
509
510#include <bdlscm_version.h>
511
512#include <bsls_assert.h>
513
514
515namespace bdlt {
516
517 // =======================
518 // struct PosixDateImpUtil
519 // =======================
520
521/// This `struct` provides a namespace for a suite of pure functions that
522/// perform low-level operations on date values in a variety of formats.
523/// Note that all of these functions, whether or not implemented in terms of
524/// a static cache, are stateless, and, as such, are inherently thread-safe.
526
527 private:
528 // PRIVATE TYPES
529 struct YearMonthDay{
530 short d_year;
531 char d_month;
532 char d_day;
533 };
534
535 // PRIVATE CLASS DATA
536 static const int s_firstCachedYear;
537 static const int s_lastCachedYear;
538 static const int s_firstCachedSerialDate;
539 static const int s_lastCachedSerialDate;
540 static const int s_cachedSerialDate[][13];
541 static const YearMonthDay s_cachedYearMonthDay[];
542 static const char s_cachedDaysInMonth[][13];
543
544 public:
545 // CLASS METHODS
546
547 /// Return `true` if the specified `year` is a leap year, and `false`
548 /// otherwise. The behavior is undefined unless `1 <= year <= 9999`.
549 static bool isLeapYear(int year);
550
551 /// Return the last day of the specified `month` in the specified
552 /// `year`. The behavior is undefined unless `1 <= year <= 9999` and
553 /// `1 <= month <= 12`. Note that the value returned will be in the
554 /// range `[ 28 .. 31 ]`.
555 static int lastDayOfMonth(int year, int month);
556
557 /// Return the number of leap years occurring between the specified
558 /// `year1` and `year2` (inclusive). The behavior is undefined unless
559 /// `1 <= year1 <= 9999`, `1 <= year2 <= 9999`, and `year1 <= year2`.
560 static int numLeapYears(int year1, int year2);
561
562 // Is Valid Date
563
564 /// Return `true` if the specified `year`, `month`, and `day` represents
565 /// a valid date value, and `false` otherwise. Note that valid date
566 /// values are (as fully defined in the component-level documentation)
567 /// in the range `[ 0001/01/01 .. 9999/12/31 ]` (except that
568 /// `[ 1752/09/03 .. 1752/09/13 ]` are not valid for historical
569 /// reasons).
570 static bool isValidYearMonthDay(int year, int month, int day);
571
572 /// Return `true` if the specified `year`, `month`, and `day` represents
573 /// a valid date value, and `false` otherwise. Note that valid date
574 /// values are (as fully defined in the component-level documentation)
575 /// in the range `[ 0001/01/01 .. 9999/12/31 ]` (except that
576 /// `[ 1752/09/03 .. 1752/09/13 ]` are not valid for historical
577 /// reasons). Also note that this function is guaranteed not to use any
578 /// date-cache optimizations.
579 static bool isValidYearMonthDayNoCache(int year, int month, int day);
580
581 /// Return `true` if the specified `serialDay` represents a valid date
582 /// value, and `false` otherwise. Note that valid date values are (as
583 /// fully defined in the component-level documentation) in the range
584 /// `[ 1 .. 3652061 ]`.
585 static bool isValidSerial(int serialDay);
586
587 /// Return `true` if the specified `year` and `dayOfYear` represents a
588 /// valid date value, and `false` otherwise. Note that valid date
589 /// values are (as fully defined in the component-level documentation)
590 /// in the range `[ 0001/01 .. 9999/365 ]` (except that
591 /// `[ 1752/356 .. 1752/366 ]` are not valid for historical reasons).
592 static bool isValidYearDay(int year, int dayOfYear);
593
594 // To Serial Date (s)
595
596 /// Return the serial date representation of the date value indicated by
597 /// the specified `year` and `dayOfYear`. The behavior is undefined
598 /// unless `true == isValidYearDay(year, dayOfYear)`.
599 static int ydToSerial(int year, int dayOfYear);
600
601 /// Return the serial date representation of the date value indicated by
602 /// the specified `year`, `month`, and `day`. The behavior is undefined
603 /// unless `true == isValidYearMonthDay(year, month, day)`.
604 static int ymdToSerial(int year, int month, int day);
605
606 /// Return the serial date representation of the date value indicated by
607 /// the specified `year`, `month`, and `day`. The behavior is undefined
608 /// unless `true == isValidYearMonthDay(year, month, day)`. Note that
609 /// this function is guaranteed not to use any date-cache optimizations.
610 static int ymdToSerialNoCache(int year, int month, int day);
611
612 // To Day-Of-Year Date (yd)
613
614 /// Return the day of the year of the date value indicated by the
615 /// specified `serialDay`. The behavior is undefined unless
616 /// `true == isValidSerial(serialDay)`.
617 static int serialToDayOfYear(int serialDay);
618
619 /// Load, into the specified `year` and `dayOfYear`, the year-day
620 /// representation of the date value indicated by the specified
621 /// `serialDay`. The behavior is undefined unless
622 /// `true == isValidSerial(serialDay)`.
623 static void serialToYd(int *year, int *dayOfYear, int serialDay);
624
625 /// Return the day of the year of the date value indicated by the
626 /// specified `year`, `month`, and `day`. The behavior is undefined
627 /// unless `true == isValidYearMonthDay(year, month, day)`.
628 static int ymdToDayOfYear(int year, int month, int day);
629
630 // To Calendar Date (ymd)
631
632 /// Return the day (of the month) of the date value indicated by the
633 /// specified `serialDay`. The behavior is undefined unless
634 /// `true == isValidSerial(serialDay)`.
635 static int serialToDay(int serialDay);
636
637 /// Return the day (of the month) of the date value indicated by the
638 /// specified `serialDay`. The behavior is undefined unless
639 /// `true == isValidSerial(serialDay)`. Note that this function is
640 /// guaranteed not to use any date-cache optimizations.
641 static int serialToDayNoCache(int serialDay);
642
643 /// Return the month of the date value indicated by the specified
644 /// `serialDay`. The behavior is undefined unless
645 /// `true == isValidSerial(serialDay)`.
646 static int serialToMonth(int serialDay);
647
648 /// Return the month of the date value indicated by the specified
649 /// `serialDay`. The behavior is undefined unless
650 /// `true == isValidSerial(serialDay)`. Note that this function is
651 /// guaranteed not to use any date-cache optimizations.
652 static int serialToMonthNoCache(int serialDay);
653
654 /// Return the year of the date value indicated by the specified
655 /// `serialDay`. The behavior is undefined unless
656 /// `true == isValidSerial(serialDay)`.
657 static int serialToYear(int serialDay);
658
659 /// Return the year of the date value indicated by the specified
660 /// `serialDay`. The behavior is undefined unless
661 /// `true == isValidSerial(serialDay)`. Note that this function is
662 /// guaranteed not to use any date-cache optimizations.
663 static int serialToYearNoCache(int serialDay);
664
665 /// Load, into the specified `year`, `month`, and `day`, the date value
666 /// indicated by the specified `serialDay`. The behavior is undefined
667 /// unless `true == isValidSerial(serialDay)`.
668 static void serialToYmd(int *year, int *month, int *day, int serialDay);
669
670 /// Load, into the specified `year`, `month`, and `day`, the date value
671 /// indicated by the specified `serialDay`. The behavior is undefined
672 /// unless `true == isValidSerial(serialDay)`. Note that this function
673 /// is guaranteed not to use any date-cache-optimizations.
674 static void serialToYmdNoCache(int *year,
675 int *month,
676 int *day,
677 int serialDay);
678
679 /// Return the day (of the month) of the date value indicated by the
680 /// specified `year` and `dayOfYear`. The behavior is undefined unless
681 /// `true == isValidYearDay(year, dayOfYear)`.
682 static int ydToDay(int year, int dayOfYear);
683
684 /// Load, into the specified `month` and `day`, the (partial) calendar
685 /// date representation of the date value indicated by the specified
686 /// `year` and `dayOfYear`. The behavior is undefined unless
687 /// `true == isValidYearDay(year, dayOfYear)`.
688 static void ydToMd(int *month, int *day, int year, int dayOfYear);
689
690 /// Return the month of the date value indicated by the specified `year`
691 /// and `dayOfYear`. The behavior is undefined unless
692 /// `true == isValidYearDay(year, dayOfYear)`.
693 static int ydToMonth(int year, int dayOfYear);
694
695 // To Day of Week '[ SUN = 1, MON .. SAT ]'
696
697 /// Return, as an integer (with `1 = SUN`, `2 = MON`, ..., and
698 /// `7 = SAT`), the day (of the week) of the date value indicated by the
699 /// specified `serialDay`. The behavior is undefined unless
700 /// `true == isValidSerial(serialDay)`.
701 static int serialToDayOfWeek(int serialDay);
702
703 /// Return, as an integer (with `1 = SUN`, `2 = MON`, ..., and
704 /// `7 = SAT`), the day (of the week) of the date value indicated by the
705 /// specified `year` and `dayOfYear`. The behavior is undefined unless
706 /// `true == isValidYearDay(year, dayOfYear)`.
707 static int ydToDayOfWeek(int year, int dayOfYear);
708
709 /// Return, as an integer (with `1 = SUN`, `2 = MON`, ..., and
710 /// `7 = SAT`), the day (of the week) of the date value indicated by the
711 /// specified `year`, `month`, and `day`. The behavior is undefined
712 /// unless `true == isValidYearMonthDay(year, month, day)`.
713 static int ymdToDayOfWeek(int year, int month, int day);
714};
715
716// ============================================================================
717// INLINE DEFINITIONS
718// ============================================================================
719
720 // -----------------------
721 // struct PosixDateImpUtil
722 // -----------------------
723
724// CLASS METHODS
725inline
727{
728 BSLS_ASSERT_SAFE(1 <= year); BSLS_ASSERT_SAFE(year <= 9999);
729
730 // Note relative probabilities: (1) not a modern leap year (most likely),
731 // (2) not turn of any century (e.g., was not 2000), (3) year was a
732 // multiple of 400 (e.g., was 2000), and (4) year was not after 1752 (most
733 // unlikely).
734
735 return 0 == year % 4
736 && (0 != year % 100 || 0 == year % 400 || year <= 1752);
737}
738
739 // Is Valid Date
740
741inline
742bool PosixDateImpUtil::isValidYearMonthDay(int year, int month, int day)
743{
744 // Check month and day; the cache cannot catch out-of-range issues.
745
746 if (month < 1 || month > 12 || day < 1) {
747 return false; // RETURN
748 }
749
750 if (s_firstCachedYear <= year && year <= s_lastCachedYear) {
751 return day <= s_cachedDaysInMonth[year - s_firstCachedYear][month];
752 // RETURN
753 }
754 else {
755 return isValidYearMonthDayNoCache(year, month, day); // RETURN
756 }
757}
758
759inline
761{
762 return (static_cast<unsigned>(serialDay) - 1) < 3652061; // # == 9999/12/31
763}
764
765 // To Day-Of-Year Date (yd)
766
767inline
769{
770 BSLS_ASSERT_SAFE(true == isValidSerial(serialDay));
771
772 int dayOfYear, year;
773 serialToYd(&year, &dayOfYear, serialDay);
774 return dayOfYear;
775}
776
777 // To Calendar Date (ymd)
778
779inline
781{
782 BSLS_ASSERT_SAFE(true == isValidSerial(serialDay));
783
784 int year, month, day;
785 serialToYmdNoCache(&year, &month, &day, serialDay);
786 return day;
787}
788
789inline
791{
792 BSLS_ASSERT_SAFE(true == isValidSerial(serialDay));
793
794 int year, month, day;
795 serialToYmdNoCache(&year, &month, &day, serialDay);
796 return month;
797}
798
799inline
801{
802 BSLS_ASSERT_SAFE(true == isValidSerial(serialDay));
803
804 int year, month, day;
805 serialToYmdNoCache(&year, &month, &day, serialDay);
806 return year;
807}
808
809inline
811 int *month,
812 int *day,
813 int serialDay)
814{
815 BSLS_ASSERT_SAFE(year);
816 BSLS_ASSERT_SAFE(month);
817 BSLS_ASSERT_SAFE(day);
818 BSLS_ASSERT_SAFE(true == isValidSerial(serialDay));
819
820 int dayOfYear;
821 serialToYd(year, &dayOfYear, serialDay);
822 ydToMd(month, day, *year, dayOfYear);
823}
824
825inline
826int PosixDateImpUtil::ydToDay(int year, int dayOfYear)
827{
828 BSLS_ASSERT_SAFE(true == isValidYearDay(year, dayOfYear));
829
830 int month, day;
831 ydToMd(&month, &day, year, dayOfYear);
832 return day;
833}
834
835inline
836int PosixDateImpUtil::ydToMonth(int year, int dayOfYear)
837{
838 BSLS_ASSERT_SAFE(true == isValidYearDay(year, dayOfYear));
839
840 int month, day;
841 ydToMd(&month, &day, year, dayOfYear);
842 return month;
843}
844
845 // To Day of Week '[ SUN = 1, MON .. SAT ]'
846
847inline
848int PosixDateImpUtil::ydToDayOfWeek(int year, int dayOfYear)
849{
850 BSLS_ASSERT_SAFE(true == isValidYearDay(year, dayOfYear));
851
852 return serialToDayOfWeek(ydToSerial(year, dayOfYear));
853}
854
855inline
856int PosixDateImpUtil::ymdToDayOfWeek(int year, int month, int day)
857{
858 BSLS_ASSERT_SAFE(true == isValidYearMonthDay(year, month, day));
859
860 return serialToDayOfWeek(ymdToSerial(year, month, day));
861}
862
863} // close package namespace
864
865
866#endif
867
868// ----------------------------------------------------------------------------
869// Copyright 2014 Bloomberg Finance L.P.
870//
871// Licensed under the Apache License, Version 2.0 (the "License");
872// you may not use this file except in compliance with the License.
873// You may obtain a copy of the License at
874//
875// http://www.apache.org/licenses/LICENSE-2.0
876//
877// Unless required by applicable law or agreed to in writing, software
878// distributed under the License is distributed on an "AS IS" BASIS,
879// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
880// See the License for the specific language governing permissions and
881// limitations under the License.
882// ----------------------------- END-OF-FILE ----------------------------------
883
884/** @} */
885/** @} */
886/** @} */
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bbldc_basicisma30360.h:112
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 void ydToMd(int *month, int *day, int year, int dayOfYear)
static int serialToYear(int serialDay)
static int serialToYearNoCache(int serialDay)
Definition bdlt_posixdateimputil.h:800
static int serialToMonth(int serialDay)
static int ymdToSerial(int year, int month, int day)
static int ymdToDayOfWeek(int year, int month, int day)
Definition bdlt_posixdateimputil.h:856
static bool isValidYearMonthDay(int year, int month, int day)
Definition bdlt_posixdateimputil.h:742
static int serialToDayNoCache(int serialDay)
Definition bdlt_posixdateimputil.h:780
static bool isValidYearMonthDayNoCache(int year, int month, int day)
static bool isValidYearDay(int year, int dayOfYear)
static int ydToDay(int year, int dayOfYear)
Definition bdlt_posixdateimputil.h:826
static int serialToDay(int serialDay)
static void serialToYmdNoCache(int *year, int *month, int *day, int serialDay)
Definition bdlt_posixdateimputil.h:810
static int ydToSerial(int year, int dayOfYear)
static int numLeapYears(int year1, int year2)
static bool isLeapYear(int year)
Definition bdlt_posixdateimputil.h:726
static int serialToMonthNoCache(int serialDay)
Definition bdlt_posixdateimputil.h:790
static int serialToDayOfWeek(int serialDay)
static int ydToMonth(int year, int dayOfYear)
Definition bdlt_posixdateimputil.h:836
static void serialToYd(int *year, int *dayOfYear, int serialDay)
static int serialToDayOfYear(int serialDay)
Definition bdlt_posixdateimputil.h:768
static int ymdToDayOfYear(int year, int month, int day)
static int lastDayOfMonth(int year, int month)
static int ydToDayOfWeek(int year, int dayOfYear)
Definition bdlt_posixdateimputil.h:848
static int ymdToSerialNoCache(int year, int month, int day)