// bdlt_posixdateimputil.h -*-C++-*- #ifndef INCLUDED_BDLT_POSIXDATEIMPUTIL #define INCLUDED_BDLT_POSIXDATEIMPUTIL #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide low-level support functions for date-value manipulation. // //@CLASSES: // bdlt::PosixDateImpUtil: suite of low-level date-related stateless functions // //@DESCRIPTION: This component implements a utility class, // 'bdlt::PosixDateImpUtil', that provides a suite of low-level, date-related // functions that can be used to validate, manipulate, and convert among values // in three different formats: //.. // YMD: year/month/day // YD: year/dayOfYear // S: serialDate //.. // The supplied functionality can also be used for determining leap years, // finding the last day in a month, and for determining the day of the week for // a given date. Note that in this component, a "date" is understood to // represent a valid day in the range '0001JAN01' to '9999DEC31', according to // the standard UNIX date implementation. // ///Representations, Valid Dates, and Leap Years ///-------------------------------------------- // The "Calendar Date", or "year-month-day (ymd)", is the primary // representation and is denoted as "yyyy/mm/dd", with valid years being in the // range '[ 1 .. 9999 ]'. Within a valid year, valid months and valid days are // confined to the respective ranges '[ 1 .. 12 ]' and '[ 1 .. 31 ]'. Valid // dates in this representation will range from '0001/01/01' to '9999/12/31', // but are also governed by the standard UNIX (Gregorian) calendar convention. // // The "Day-Of-Year Date", or "year-day (yd)" representation, denoted by // "yyyy/ddd", represents dates by their year, again in the range // '[ 1 .. 9999 ]', and the day of year, in the range '[ 1 .. 366 ]'. Note // that valid date values in this representation range from '0001/01' to // '9999/365', with a day-of-year value of 366 permitted for leap years only. // // The "Serial Date" representation depicts dates as consecutive integers, // beginning with 1 (representing '0001JAN01'). In this representation, valid // date value are in the range '[ 1 .. 3652061 ]'. // // In a leap year, February has 29 days instead of the usual 28. For years // subsequent to 1752, a year is a leap year if it is divisible by 4, but not // divisible by 100, unless it is also divisible by 400. Prior to 1752, all // years divisible by 4 were leap years. Note that the year 1752 had only // '366 - 11 = 355' days, as September 3rd through the 13th were omitted (in a // one-time correction to the previous, less accurate, leap-year convention). // ///Caching ///------- // To achieve maximal runtime performance, several of the functions in this // component reserve the right to be implemented using statically cached (i.e., // tabulated) values (which is inherently thread-safe). In all cases where a // cache may be used, 'bdlt::PosixDateImpUtil' explicitly provides a 'NoCache' // version (e.g., 'ymdToSerialNoCache') that is guaranteed NOT to use a cache. // Although the "normal" (potentially cached) functions typically gain huge // performance advantages, the 'NoCache' versions may conceivably be preferred // by the performance-minded user who is *reasonably* *certain* that the vast // majority of date values of interest will miss the cache (thus incurring a // small, but unnecessary overhead for the cache-hit tests). Note, however, // that the 'NoCache' function variants are provided primarily for testing and // for generating that cache in the first place (see // 'bdlt_posixdateimputil.t.cpp'). // ///Usage ///----- // This component was created primarily to support the implementation of a // general-purpose, value-semantic (vocabulary) "Date" type, but also provides // many low-level utility functions suitable for direct use by other clients. // ///Creating a General Purpose Utility /// - - - - - - - - - - - - - - - - - // Many of the functions provided by this component can be used directly by // clients that want to ask questions about a particular date in one of the // three supported formats. // // What day of the week was January 3, 2010? //.. // assert(2 == bdlt::PosixDateImpUtil::ymdToDayOfWeek(2010, 3, 1)); // // 2 means Monday. //.. // Was the year 2000 a leap year? //.. // assert(true == bdlt::PosixDateImpUtil::isLeapYear(2000)); // // Yes, it was. //.. // Was February 29, 1900, a valid date in history? //.. // assert(false == bdlt::PosixDateImpUtil::isValidYearMonthDay(1900, 2, 29)); // // No, it was not. //.. // What was the last day of February in 1600? //.. // assert(29 == bdlt::PosixDateImpUtil::lastDayOfMonth(1600, 2)); // // The 29th. //.. // How many leap years occur from 1959 to 2012 inclusive? //.. // assert(14 == bdlt::PosixDateImpUtil::numLeapYears(1959, 2012)); // // There are 14. //.. // On what day of the year does February 29, 2020 fall? //.. // assert(60 == bdlt::PosixDateImpUtil::ymdToDayOfYear(2020, 2, 29)); // // The 60th one. //.. // In what month does the 120th day of 2011 fall? //.. // assert(4 == bdlt::PosixDateImpUtil::ydToMonth(2011, 120)); // // 4 means April. //.. // ///Implementing a Value-Semantic Date Type ///- - - - - - - - - - - - - - - - - - - - // Using the functions supplied in this component, we can easily implement a // C++ class that represents abstract (*mathematical*) date values and performs // a few common operations on them. The internal representation could be any // of the three supported by this component; in this example, we will choose to // represent the date value internally as a "serial date": //.. // class MyDate { // // This class represents a valid date in the range // // '[ 0001/01/01 .. 9999/12/31 ]'. // // // DATA // int d_serialDate; // 1 = 0001JAN01, 2 = 0001JAN02, ... // // // FRIENDS // friend MyDate operator+(const MyDate&, int); // friend MyDate operator+(int, const MyDate&); // friend int operator- (const MyDate&, const MyDate&); // friend bool operator==(const MyDate&, const MyDate&); // // private: // // PRIVATE CREATORS // explicit MyDate(int serialDate); //.. // Next we define the public interface of the class, with function-level // documentation conspicuously omitted (note, however, that reference // implementations with preconditions asserted will follow): //.. // public: // // TYPES // enum Day { // SUN = 1, // MON = 2, // TUE = 3, // WED = 4, // THU = 5, // FRI = 6, // SAT = 7 // }; // // // CLASS METHODS // static bool isValid(int year, int month, int day); // // // CREATORS // MyDate(); // MyDate(const MyDate& original); // ~MyDate(); // // // MANIPULATORS // MyDate& operator=(const MyDate& rhs); // MyDate& operator++(); // MyDate& operator--(); // MyDate& operator+=(int numDays); // MyDate& operator-=(int numDays); // void setYearMonthDay(int year, int month, int day); // bool setYearMonthDayIfValid(int year, int month, int day); // // // ACCESSORS // void getYearMonthDay(int *year, int *month, int *day) const; // int year() const; // int month() const; // int day() const; // Day dayOfWeek() const; // bool isLeapYear() const; // bsl::ostream& print(bsl::ostream& stream) const; // }; // // // FREE OPERATORS // bool operator==(const MyDate& lhs, const MyDate& rhs); // bool operator!=(const MyDate& lhs, const MyDate& rhs); // // bsl::ostream& operator<<(bsl::ostream& stream, const MyDate& rhs); // // MyDate operator+(const MyDate& lhs, int rhs); // MyDate operator+(int lhs, const MyDate& rhs); // // int operator-(const MyDate& lhs, const MyDate& rhs); // // MyDate operator++(MyDate& object, int); // MyDate operator--(MyDate& object, int); //.. // We now provide a reference implementation of each of the methods and free // (operator) functions associated with the 'MyDate' class defined above (using // 'bsls_assert' to identify preconditions and invariants where appropriate): //.. // // PRIVATE CREATORS // inline // MyDate::MyDate(int serialDate) // : d_serialDate(serialDate) // { // } // // // CLASS METHODS // inline // bool MyDate::isValid(int year, int month, int day) // { // return bdlt::PosixDateImpUtil::isValidYearMonthDay(year, month, day); // } // // // CREATORS // inline // MyDate::MyDate() // : d_serialDate(1) // { // } // // inline // MyDate::MyDate(const MyDate& original) // : d_serialDate(original.d_serialDate) // { // } // // inline // MyDate::~MyDate() // { // } // // // MANIPULATORS // inline // MyDate& MyDate::operator=(const MyDate& rhs) // { // d_serialDate = rhs.d_serialDate; // return *this; // } // // inline // MyDate& MyDate::operator++() // { // ++d_serialDate; // BSLS_ASSERT_SAFE(bdlt::PosixDateImpUtil::isValidSerial(d_serialDate)); // return *this; // } // // inline // MyDate& MyDate::operator--() // { // --d_serialDate; // BSLS_ASSERT_SAFE(bdlt::PosixDateImpUtil::isValidSerial(d_serialDate)); // return *this; // } // // inline // MyDate& MyDate::operator+=(int numDays) // { // d_serialDate += numDays; // BSLS_ASSERT_SAFE(bdlt::PosixDateImpUtil::isValidSerial(d_serialDate)); // return *this; // } // // inline // MyDate& MyDate::operator-=(int numDays) // { // d_serialDate -= numDays; // BSLS_ASSERT_SAFE(bdlt::PosixDateImpUtil::isValidSerial(d_serialDate)); // return *this; // } // // inline // void MyDate::setYearMonthDay(int year, int month, int day) // { // d_serialDate = bdlt::PosixDateImpUtil::ymdToSerial(year, month, day); // BSLS_ASSERT_SAFE(bdlt::PosixDateImpUtil::isValidSerial(d_serialDate)); // } // // inline // bool MyDate::setYearMonthDayIfValid(int year, int month, int day) // { // const int newDate = bdlt::PosixDateImpUtil::ymdToSerial(year, // month, // day); // if (bdlt::PosixDateImpUtil::isValidSerial(newDate)) { // d_serialDate = newDate; // return true; // RETURN // } // return false; // } // // // ACCESSORS // inline // void MyDate::getYearMonthDay(int *year, int *month, int *day) const // { // bdlt::PosixDateImpUtil::serialToYmd(year, month, day, d_serialDate); // } // // inline // int MyDate::year() const // { // return bdlt::PosixDateImpUtil::serialToYear(d_serialDate); // } // // inline // int MyDate::month() const // { // return bdlt::PosixDateImpUtil::serialToMonth(d_serialDate); // } // // inline // int MyDate::day() const // { // return bdlt::PosixDateImpUtil::serialToDay(d_serialDate); // } // // inline // MyDate::Day MyDate::dayOfWeek() const // { // return MyDate::Day(bdlt::PosixDateImpUtil::serialToDayOfWeek( // d_serialDate)); // } // // inline // bool MyDate::isLeapYear() const // { // return bdlt::PosixDateImpUtil::isLeapYear(year()); // } // // // FREE OPERATORS // inline // bool operator==(const MyDate& lhs, const MyDate& rhs) // { // return lhs.d_serialDate == rhs.d_serialDate; // } // // inline // bool operator!=(const MyDate& lhs, const MyDate& rhs) // { // return !(lhs == rhs); // } // // inline // bsl::ostream& operator<<(bsl::ostream& stream, const MyDate& rhs) // { // return rhs.print(stream); // } // // inline // MyDate operator+(const MyDate& lhs, int rhs) // { // return MyDate(lhs.d_serialDate + rhs); // } // // inline // MyDate operator+(int lhs, const MyDate& rhs) // { // return MyDate(lhs + rhs.d_serialDate); // } // // inline // int operator-(const MyDate& lhs, const MyDate& rhs) // { // return lhs.d_serialDate - rhs.d_serialDate; // } // // inline // MyDate operator++(MyDate& object, int) // { // MyDate tmp(object); // ++object; // return tmp; // } // // inline // MyDate operator--(MyDate& object, int) // { // MyDate tmp(object); // --object; // return tmp; // } //.. // The following definitions would appropriately appear in the implementation // ('.cpp') file: //.. // const char *const monthNames[] = { // 0, "JAN", "FEB", "MAR", "APR", // "MAY", "JUN", "JUL", "AUG", // "SEP", "OCT", "NOV", "DEC" // }; // // // MANIPULATORS // bsl::ostream& MyDate::print(bsl::ostream& stream) const // { // if (!stream) { // return stream; // RETURN // } // // // space usage: ddMMMyyyy null // const int SIZE = 2 + 3 + 4 + 1; // char buf[SIZE]; // // int y, m, d; // bdlt::PosixDateImpUtil::serialToYmd(&y, &m, &d, d_serialDate); // // buf[0] = d / 10 + '0'; // buf[1] = d % 10 + '0'; // // bsl::memcpy(&buf[2], monthNames[m], 3); // // buf[5] = y / 1000 + '0'; // buf[6] = ((y % 1000) / 100) + '0'; // buf[7] = ((y % 100) / 10) + '0'; // buf[8] = y % 10 + '0'; // buf[9] = 0; // // stream << buf; // // return stream; // } //.. // The following snippets of code illustrate how to create and use a 'Mydate' // object. First create a default object, 'd1': //.. // MyDate d1; assert( 1 == d1.year()); // assert( 1 == d1.month()); // assert( 1 == d1.day()); //.. // Next, set 'd1' to July 4, 1776: //.. // d1.setYearMonthDay(1776, 7, 4); assert(1776 == d1.year()); // assert( 7 == d1.month()); // assert( 4 == d1.day()); //.. // Then create 'd2' as a copy of 'd1': //.. // MyDate d2(d1); assert(1776 == d2.year()); // assert( 7 == d2.month()); // assert( 4 == d2.day()); //.. // Now, add six days to the value of 'd2': //.. // d2 += 6; assert(1776 == d2.year()); // assert( 7 == d2.month()); // assert( 10 == d2.day()); //.. // Next subtract 'd1' from 'd2', storing the difference (in days) in 'dDays': //.. // int dDays = d2 - d1; assert(6 == dDays); //.. // Finally, stream the value of 'd2' to 'stdout': //.. // bsl::cout << d2 << bsl::endl; //.. // The streaming operator produces the following output on 'stdout': //.. // 10JUL1776 //.. #include <bdlscm_version.h> #include <bsls_assert.h> namespace BloombergLP { namespace bdlt { // ======================= // struct PosixDateImpUtil // ======================= struct PosixDateImpUtil { // This 'struct' provides a namespace for a suite of pure functions that // perform low-level operations on date values in a variety of formats. // Note that all of these functions, whether or not implemented in terms of // a static cache, are stateless, and, as such, are inherently thread-safe. private: // PRIVATE TYPES struct YearMonthDay{ short d_year; char d_month; char d_day; }; // PRIVATE CLASS DATA static const int s_firstCachedYear; static const int s_lastCachedYear; static const int s_firstCachedSerialDate; static const int s_lastCachedSerialDate; static const int s_cachedSerialDate[][13]; static const YearMonthDay s_cachedYearMonthDay[]; static const char s_cachedDaysInMonth[][13]; public: // CLASS METHODS static bool isLeapYear(int year); // Return 'true' if the specified 'year' is a leap year, and 'false' // otherwise. The behavior is undefined unless '1 <= year <= 9999'. static int lastDayOfMonth(int year, int month); // Return the last day of the specified 'month' in the specified // 'year'. The behavior is undefined unless '1 <= year <= 9999' and // '1 <= month <= 12'. Note that the value returned will be in the // range '[ 28 .. 31 ]'. static int numLeapYears(int year1, int year2); // Return the number of leap years occurring between the specified // 'year1' and 'year2' (inclusive). The behavior is undefined unless // '1 <= year1 <= 9999', '1 <= year2 <= 9999', and 'year1 <= year2'. // Is Valid Date static bool isValidYearMonthDay(int year, int month, int day); // Return 'true' if the specified 'year', 'month', and 'day' represents // a valid date value, and 'false' otherwise. Note that valid date // values are (as fully defined in the component-level documentation) // in the range '[ 0001/01/01 .. 9999/12/31 ]' (except that // '[ 1752/09/03 .. 1752/09/13 ]' are not valid for historical // reasons). static bool isValidYearMonthDayNoCache(int year, int month, int day); // Return 'true' if the specified 'year', 'month', and 'day' represents // a valid date value, and 'false' otherwise. Note that valid date // values are (as fully defined in the component-level documentation) // in the range '[ 0001/01/01 .. 9999/12/31 ]' (except that // '[ 1752/09/03 .. 1752/09/13 ]' are not valid for historical // reasons). Also note that this function is guaranteed not to use any // date-cache optimizations. static bool isValidSerial(int serialDay); // Return 'true' if the specified 'serialDay' represents a valid date // value, and 'false' otherwise. Note that valid date values are (as // fully defined in the component-level documentation) in the range // '[ 1 .. 3652061 ]'. static bool isValidYearDay(int year, int dayOfYear); // Return 'true' if the specified 'year' and 'dayOfYear' represents a // valid date value, and 'false' otherwise. Note that valid date // values are (as fully defined in the component-level documentation) // in the range '[ 0001/01 .. 9999/365 ]' (except that // '[ 1752/356 .. 1752/366 ]' are not valid for historical reasons). // To Serial Date (s) static int ydToSerial(int year, int dayOfYear); // Return the serial date representation of the date value indicated by // the specified 'year' and 'dayOfYear'. The behavior is undefined // unless 'true == isValidYearDay(year, dayOfYear)'. static int ymdToSerial(int year, int month, int day); // Return the serial date representation of the date value indicated by // the specified 'year', 'month', and 'day'. The behavior is undefined // unless 'true == isValidYearMonthDay(year, month, day)'. static int ymdToSerialNoCache(int year, int month, int day); // Return the serial date representation of the date value indicated by // the specified 'year', 'month', and 'day'. The behavior is undefined // unless 'true == isValidYearMonthDay(year, month, day)'. Note that // this function is guaranteed not to use any date-cache optimizations. // To Day-Of-Year Date (yd) static int serialToDayOfYear(int serialDay); // Return the day of the year of the date value indicated by the // specified 'serialDay'. The behavior is undefined unless // 'true == isValidSerial(serialDay)'. static void serialToYd(int *year, int *dayOfYear, int serialDay); // Load, into the specified 'year' and 'dayOfYear', the year-day // representation of the date value indicated by the specified // 'serialDay'. The behavior is undefined unless // 'true == isValidSerial(serialDay)'. static int ymdToDayOfYear(int year, int month, int day); // Return the day of the year of the date value indicated by the // specified 'year', 'month', and 'day'. The behavior is undefined // unless 'true == isValidYearMonthDay(year, month, day)'. // To Calendar Date (ymd) static int serialToDay(int serialDay); // Return the day (of the month) of the date value indicated by the // specified 'serialDay'. The behavior is undefined unless // 'true == isValidSerial(serialDay)'. static int serialToDayNoCache(int serialDay); // Return the day (of the month) of the date value indicated by the // specified 'serialDay'. The behavior is undefined unless // 'true == isValidSerial(serialDay)'. Note that this function is // guaranteed not to use any date-cache optimizations. static int serialToMonth(int serialDay); // Return the month of the date value indicated by the specified // 'serialDay'. The behavior is undefined unless // 'true == isValidSerial(serialDay)'. static int serialToMonthNoCache(int serialDay); // Return the month of the date value indicated by the specified // 'serialDay'. The behavior is undefined unless // 'true == isValidSerial(serialDay)'. Note that this function is // guaranteed not to use any date-cache optimizations. static int serialToYear(int serialDay); // Return the year of the date value indicated by the specified // 'serialDay'. The behavior is undefined unless // 'true == isValidSerial(serialDay)'. static int serialToYearNoCache(int serialDay); // Return the year of the date value indicated by the specified // 'serialDay'. The behavior is undefined unless // 'true == isValidSerial(serialDay)'. Note that this function is // guaranteed not to use any date-cache optimizations. static void serialToYmd(int *year, int *month, int *day, int serialDay); // Load, into the specified 'year', 'month', and 'day', the date value // indicated by the specified 'serialDay'. The behavior is undefined // unless 'true == isValidSerial(serialDay)'. static void serialToYmdNoCache(int *year, int *month, int *day, int serialDay); // Load, into the specified 'year', 'month', and 'day', the date value // indicated by the specified 'serialDay'. The behavior is undefined // unless 'true == isValidSerial(serialDay)'. Note that this function // is guaranteed not to use any date-cache-optimizations. static int ydToDay(int year, int dayOfYear); // Return the day (of the month) of the date value indicated by the // specified 'year' and 'dayOfYear'. The behavior is undefined unless // 'true == isValidYearDay(year, dayOfYear)'. static void ydToMd(int *month, int *day, int year, int dayOfYear); // Load, into the specified 'month' and 'day', the (partial) calendar // date representation of the date value indicated by the specified // 'year' and 'dayOfYear'. The behavior is undefined unless // 'true == isValidYearDay(year, dayOfYear)'. static int ydToMonth(int year, int dayOfYear); // Return the month of the date value indicated by the specified 'year' // and 'dayOfYear'. The behavior is undefined unless // 'true == isValidYearDay(year, dayOfYear)'. // To Day of Week '[ SUN = 1, MON .. SAT ]' static int serialToDayOfWeek(int serialDay); // Return, as an integer (with '1 = SUN', '2 = MON', ..., and // '7 = SAT'), the day (of the week) of the date value indicated by the // specified 'serialDay'. The behavior is undefined unless // 'true == isValidSerial(serialDay)'. static int ydToDayOfWeek(int year, int dayOfYear); // Return, as an integer (with '1 = SUN', '2 = MON', ..., and // '7 = SAT'), the day (of the week) of the date value indicated by the // specified 'year' and 'dayOfYear'. The behavior is undefined unless // 'true == isValidYearDay(year, dayOfYear)'. static int ymdToDayOfWeek(int year, int month, int day); // Return, as an integer (with '1 = SUN', '2 = MON', ..., and // '7 = SAT'), the day (of the week) of the date value indicated by the // specified 'year', 'month', and 'day'. The behavior is undefined // unless 'true == isValidYearMonthDay(year, month, day)'. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ----------------------- // struct PosixDateImpUtil // ----------------------- // CLASS METHODS inline bool PosixDateImpUtil::isLeapYear(int year) { BSLS_ASSERT_SAFE(1 <= year); BSLS_ASSERT_SAFE(year <= 9999); // Note relative probabilities: (1) not a modern leap year (most likely), // (2) not turn of any century (e.g., was not 2000), (3) year was a // multiple of 400 (e.g., was 2000), and (4) year was not after 1752 (most // unlikely). return 0 == year % 4 && (0 != year % 100 || 0 == year % 400 || year <= 1752); } // Is Valid Date inline bool PosixDateImpUtil::isValidYearMonthDay(int year, int month, int day) { // Check month and day; the cache cannot catch out-of-range issues. if (month < 1 || month > 12 || day < 1) { return false; // RETURN } if (s_firstCachedYear <= year && year <= s_lastCachedYear) { return day <= s_cachedDaysInMonth[year - s_firstCachedYear][month]; // RETURN } else { return isValidYearMonthDayNoCache(year, month, day); // RETURN } } inline bool PosixDateImpUtil::isValidSerial(int serialDay) { return (static_cast<unsigned>(serialDay) - 1) < 3652061; // # == 9999/12/31 } // To Day-Of-Year Date (yd) inline int PosixDateImpUtil::serialToDayOfYear(int serialDay) { BSLS_ASSERT_SAFE(true == isValidSerial(serialDay)); int dayOfYear, year; serialToYd(&year, &dayOfYear, serialDay); return dayOfYear; } // To Calendar Date (ymd) inline int PosixDateImpUtil::serialToDayNoCache(int serialDay) { BSLS_ASSERT_SAFE(true == isValidSerial(serialDay)); int year, month, day; serialToYmdNoCache(&year, &month, &day, serialDay); return day; } inline int PosixDateImpUtil::serialToMonthNoCache(int serialDay) { BSLS_ASSERT_SAFE(true == isValidSerial(serialDay)); int year, month, day; serialToYmdNoCache(&year, &month, &day, serialDay); return month; } inline int PosixDateImpUtil::serialToYearNoCache(int serialDay) { BSLS_ASSERT_SAFE(true == isValidSerial(serialDay)); int year, month, day; serialToYmdNoCache(&year, &month, &day, serialDay); return year; } inline void PosixDateImpUtil::serialToYmdNoCache(int *year, int *month, int *day, int serialDay) { BSLS_ASSERT_SAFE(year); BSLS_ASSERT_SAFE(month); BSLS_ASSERT_SAFE(day); BSLS_ASSERT_SAFE(true == isValidSerial(serialDay)); int dayOfYear; serialToYd(year, &dayOfYear, serialDay); ydToMd(month, day, *year, dayOfYear); } inline int PosixDateImpUtil::ydToDay(int year, int dayOfYear) { BSLS_ASSERT_SAFE(true == isValidYearDay(year, dayOfYear)); int month, day; ydToMd(&month, &day, year, dayOfYear); return day; } inline int PosixDateImpUtil::ydToMonth(int year, int dayOfYear) { BSLS_ASSERT_SAFE(true == isValidYearDay(year, dayOfYear)); int month, day; ydToMd(&month, &day, year, dayOfYear); return month; } // To Day of Week '[ SUN = 1, MON .. SAT ]' inline int PosixDateImpUtil::ydToDayOfWeek(int year, int dayOfYear) { BSLS_ASSERT_SAFE(true == isValidYearDay(year, dayOfYear)); return serialToDayOfWeek(ydToSerial(year, dayOfYear)); } inline int PosixDateImpUtil::ymdToDayOfWeek(int year, int month, int day) { BSLS_ASSERT_SAFE(true == isValidYearMonthDay(year, month, day)); return serialToDayOfWeek(ymdToSerial(year, month, day)); } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2014 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------