Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:35:23

0001 /* Copyright (c) 2002,2003 CrystalClear Software, Inc.
0002  * Use, modification and distribution is subject to the
0003  * Boost Software License, Version 1.0. (See accompanying
0004  * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
0005  * Author: Jeff Garland, Bart Garst
0006  * $Date$
0007  */
0008 
0009 
0010 namespace boost {
0011 namespace date_time {
0012   //! Return the day of the week (0==Sunday, 1==Monday, etc)
0013   /*! Converts a year-month-day into a day of the week number
0014    */
0015   template<typename ymd_type_, typename date_int_type_>
0016   BOOST_CXX14_CONSTEXPR
0017   inline
0018   unsigned short
0019   gregorian_calendar_base<ymd_type_,date_int_type_>::day_of_week(const ymd_type& ymd) {
0020     unsigned short a = static_cast<unsigned short>((14-ymd.month)/12);
0021     unsigned short y = static_cast<unsigned short>(ymd.year - a);
0022     unsigned short m = static_cast<unsigned short>(ymd.month + 12*a - 2);
0023     unsigned short d = static_cast<unsigned short>((ymd.day + y + (y/4) - (y/100) + (y/400) + (31*m)/12) % 7);
0024     //std::cout << year << "-" << month << "-" << day << " is day: " << d << "\n";
0025     return d;
0026   }
0027 
0028   //!Return the ISO 8601 week number for the date
0029   /*!Implements the rules associated with the ISO 8601 week number.
0030     Basically the rule is that Week 1 of the year is the week that contains
0031     January 4th or the week that contains the first Thursday in January.
0032     Reference for this algorithm is the Calendar FAQ by Claus Tondering, April 2000.
0033   */
0034   template<typename ymd_type_, typename date_int_type_>
0035   BOOST_CXX14_CONSTEXPR
0036   inline
0037   int
0038   gregorian_calendar_base<ymd_type_,date_int_type_>::week_number(const ymd_type& ymd) {
0039     unsigned long julianbegin = julian_day_number(ymd_type(ymd.year,1,1));
0040     unsigned long juliantoday = julian_day_number(ymd);
0041     unsigned long day = (julianbegin + 3) % 7;
0042     unsigned long week = (juliantoday + day - julianbegin + 4)/7;
0043 
0044     if ((week >= 1) && (week <= 52)) {
0045       return static_cast<int>(week);
0046     }
0047 
0048     if (week == 53) {
0049       if((day==6) ||(day == 5 && is_leap_year(ymd.year))) {
0050         return static_cast<int>(week); //under these circumstances week == 53.
0051       } else {
0052         return 1; //monday - wednesday is in week 1 of next year
0053       }
0054     }
0055     //if the week is not in current year recalculate using the previous year as the beginning year
0056     else if (week == 0) {
0057       julianbegin = julian_day_number(ymd_type(static_cast<unsigned short>(ymd.year-1),1,1));
0058       juliantoday = julian_day_number(ymd);
0059       day = (julianbegin + 3) % 7;
0060       week = (juliantoday + day - julianbegin + 4)/7;
0061       return static_cast<int>(week);
0062     }
0063 
0064     return static_cast<int>(week);  //not reachable -- well except if day == 5 and is_leap_year != true
0065 
0066   }
0067 
0068   //! Convert a ymd_type into a day number
0069   /*! The day number is an absolute number of days since the start of count
0070    */
0071   template<typename ymd_type_, typename date_int_type_>
0072   BOOST_CXX14_CONSTEXPR
0073   inline
0074   date_int_type_
0075   gregorian_calendar_base<ymd_type_,date_int_type_>::day_number(const ymd_type& ymd)
0076   {
0077     unsigned short a = static_cast<unsigned short>((14-ymd.month)/12);
0078     unsigned short y = static_cast<unsigned short>(ymd.year + 4800 - a);
0079     unsigned short m = static_cast<unsigned short>(ymd.month + 12*a - 3);
0080     unsigned long  d = static_cast<unsigned long>(ymd.day) + ((153*m + 2)/5) + 365*y + (y/4) - (y/100) + (y/400) - 32045;
0081     return static_cast<date_int_type>(d);
0082   }
0083 
0084   //! Convert a year-month-day into the julian day number
0085   /*! Since this implementation uses julian day internally, this is the same as the day_number.
0086    */
0087   template<typename ymd_type_, typename date_int_type_>
0088   BOOST_CXX14_CONSTEXPR
0089   inline
0090   date_int_type_
0091   gregorian_calendar_base<ymd_type_,date_int_type_>::julian_day_number(const ymd_type& ymd)
0092   {
0093     return day_number(ymd);
0094   }
0095 
0096   //! Convert year-month-day into a modified julian day number
0097   /*! The day number is an absolute number of days.
0098    *  MJD 0 thus started on 17 Nov 1858(Gregorian) at 00:00:00 UTC
0099    */
0100   template<typename ymd_type_, typename date_int_type_>
0101   BOOST_CXX14_CONSTEXPR
0102   inline
0103   date_int_type_
0104   gregorian_calendar_base<ymd_type_,date_int_type_>::modjulian_day_number(const ymd_type& ymd)
0105   {
0106     return julian_day_number(ymd)-2400001; //prerounded
0107   }
0108 
0109   //! Change a day number into a year-month-day
0110   template<typename ymd_type_, typename date_int_type_>
0111   BOOST_CXX14_CONSTEXPR
0112   inline
0113   ymd_type_
0114   gregorian_calendar_base<ymd_type_,date_int_type_>::from_day_number(date_int_type dayNumber)
0115   {
0116     date_int_type a = dayNumber + 32044;
0117     date_int_type b = (4*a + 3)/146097;
0118     date_int_type c = a-((146097*b)/4);
0119     date_int_type d = (4*c + 3)/1461;
0120     date_int_type e = c - (1461*d)/4;
0121     date_int_type m = (5*e + 2)/153;
0122     unsigned short day = static_cast<unsigned short>(e - ((153*m + 2)/5) + 1);
0123     unsigned short month = static_cast<unsigned short>(m + 3 - 12 * (m/10));
0124     year_type year = static_cast<unsigned short>(100*b + d - 4800 + (m/10));
0125     //std::cout << year << "-" << month << "-" << day << "\n";
0126 
0127     return ymd_type(static_cast<unsigned short>(year),month,day);
0128   }
0129 
0130   //! Change a day number into a year-month-day
0131   template<typename ymd_type_, typename date_int_type_>
0132   BOOST_CXX14_CONSTEXPR
0133   inline
0134   ymd_type_
0135   gregorian_calendar_base<ymd_type_,date_int_type_>::from_julian_day_number(date_int_type dayNumber)
0136   {
0137     date_int_type a = dayNumber + 32044;
0138     date_int_type b = (4*a+3)/146097;
0139     date_int_type c = a - ((146097*b)/4);
0140     date_int_type d = (4*c + 3)/1461;
0141     date_int_type e = c - ((1461*d)/4);
0142     date_int_type m = (5*e + 2)/153;
0143     unsigned short day = static_cast<unsigned short>(e - ((153*m + 2)/5) + 1);
0144     unsigned short month = static_cast<unsigned short>(m + 3 - 12 * (m/10));
0145     year_type year = static_cast<year_type>(100*b + d - 4800 + (m/10));
0146     //std::cout << year << "-" << month << "-" << day << "\n";
0147 
0148     return ymd_type(year,month,day);
0149   }
0150 
0151   //! Change a modified julian day number into a year-month-day
0152   template<typename ymd_type_, typename date_int_type_>
0153   BOOST_CXX14_CONSTEXPR
0154   inline
0155   ymd_type_
0156   gregorian_calendar_base<ymd_type_,date_int_type_>::from_modjulian_day_number(date_int_type dayNumber) {
0157     date_int_type jd = dayNumber + 2400001; //is 2400000.5 prerounded
0158     return from_julian_day_number(jd);
0159   }
0160 
0161   //! Determine if the provided year is a leap year
0162   /*!
0163    *@return true if year is a leap year, false otherwise
0164    */
0165   template<typename ymd_type_, typename date_int_type_>
0166   BOOST_CXX14_CONSTEXPR
0167   inline
0168   bool
0169   gregorian_calendar_base<ymd_type_,date_int_type_>::is_leap_year(year_type year)
0170   {
0171     //divisible by 4, not if divisible by 100, but true if divisible by 400
0172     return (!(year % 4))  && ((year % 100) || (!(year % 400)));
0173   }
0174 
0175   //! Calculate the last day of the month
0176   /*! Find the day which is the end of the month given year and month
0177    *  No error checking is performed.
0178    */
0179   template<typename ymd_type_, typename date_int_type_>
0180   BOOST_CXX14_CONSTEXPR
0181   inline
0182   unsigned short
0183   gregorian_calendar_base<ymd_type_,date_int_type_>::end_of_month_day(year_type year,
0184                                                                       month_type month)
0185   {
0186     switch (month) {
0187     case 2:
0188       if (is_leap_year(year)) {
0189         return 29;
0190       } else {
0191         return 28;
0192       }
0193     case 4:
0194     case 6:
0195     case 9:
0196     case 11:
0197       return 30;
0198     default:
0199       return 31;
0200     }
0201   }
0202 
0203   //! Provide the ymd_type specification for the calendar start
0204   template<typename ymd_type_, typename date_int_type_>
0205   BOOST_CXX14_CONSTEXPR
0206   inline
0207   ymd_type_
0208   gregorian_calendar_base<ymd_type_,date_int_type_>::epoch()
0209   {
0210     return ymd_type(1400,1,1);
0211   }
0212 
0213   //! Defines length of a week for week calculations
0214   template<typename ymd_type_, typename date_int_type_>
0215   BOOST_CXX14_CONSTEXPR
0216   inline
0217   unsigned short
0218   gregorian_calendar_base<ymd_type_,date_int_type_>::days_in_week()
0219   {
0220     return 7;
0221   }
0222 
0223 
0224 } } //namespace gregorian