Line data Source code
1 : /* Copyright (c) 2002,2003 CrystalClear Software, Inc. 2 : * Use, modification and distribution is subject to the 3 : * Boost Software License, Version 1.0. (See accompanying 4 : * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) 5 : * Author: Jeff Garland, Bart Garst 6 : * $Date$ 7 : */ 8 : 9 : #ifndef NO_BOOST_DATE_TIME_INLINE 10 : #undef BOOST_DATE_TIME_INLINE 11 : #define BOOST_DATE_TIME_INLINE inline 12 : #endif 13 : 14 : namespace boost { 15 : namespace date_time { 16 : //! Return the day of the week (0==Sunday, 1==Monday, etc) 17 : /*! Converts a year-month-day into a day of the week number 18 : */ 19 : template<typename ymd_type_, typename date_int_type_> 20 : BOOST_DATE_TIME_INLINE 21 : unsigned short 22 0 : gregorian_calendar_base<ymd_type_,date_int_type_>::day_of_week(const ymd_type& ymd) { 23 0 : unsigned short a = static_cast<unsigned short>((14-ymd.month)/12); 24 0 : unsigned short y = static_cast<unsigned short>(ymd.year - a); 25 0 : unsigned short m = static_cast<unsigned short>(ymd.month + 12*a - 2); 26 0 : unsigned short d = static_cast<unsigned short>((ymd.day + y + (y/4) - (y/100) + (y/400) + (31*m)/12) % 7); 27 : //std::cout << year << "-" << month << "-" << day << " is day: " << d << "\n"; 28 0 : return d; 29 : } 30 : 31 : //!Return the iso week number for the date 32 : /*!Implements the rules associated with the iso 8601 week number. 33 : Basically the rule is that Week 1 of the year is the week that contains 34 : January 4th or the week that contains the first Thursday in January. 35 : Reference for this algorithm is the Calendar FAQ by Claus Tondering, April 2000. 36 : */ 37 : template<typename ymd_type_, typename date_int_type_> 38 : BOOST_DATE_TIME_INLINE 39 : int 40 : gregorian_calendar_base<ymd_type_,date_int_type_>::week_number(const ymd_type& ymd) { 41 : unsigned long julianbegin = julian_day_number(ymd_type(ymd.year,1,1)); 42 : unsigned long juliantoday = julian_day_number(ymd); 43 : unsigned long day = (julianbegin + 3) % 7; 44 : unsigned long week = (juliantoday + day - julianbegin + 4)/7; 45 : 46 : if ((week >= 1) && (week <= 52)) { 47 : return static_cast<int>(week); 48 : } 49 : 50 : if (week == 53) { 51 : if((day==6) ||(day == 5 && is_leap_year(ymd.year))) { 52 : return static_cast<int>(week); //under these circumstances week == 53. 53 : } else { 54 : return 1; //monday - wednesday is in week 1 of next year 55 : } 56 : } 57 : //if the week is not in current year recalculate using the previous year as the beginning year 58 : else if (week == 0) { 59 : julianbegin = julian_day_number(ymd_type(static_cast<unsigned short>(ymd.year-1),1,1)); 60 : juliantoday = julian_day_number(ymd); 61 : day = (julianbegin + 3) % 7; 62 : week = (juliantoday + day - julianbegin + 4)/7; 63 : return static_cast<int>(week); 64 : } 65 : 66 : return static_cast<int>(week); //not reachable -- well except if day == 5 and is_leap_year != true 67 : 68 : } 69 : 70 : //! Convert a ymd_type into a day number 71 : /*! The day number is an absolute number of days since the start of count 72 : */ 73 : template<typename ymd_type_, typename date_int_type_> 74 : BOOST_DATE_TIME_INLINE 75 : date_int_type_ 76 0 : gregorian_calendar_base<ymd_type_,date_int_type_>::day_number(const ymd_type& ymd) 77 : { 78 0 : unsigned short a = static_cast<unsigned short>((14-ymd.month)/12); 79 0 : unsigned short y = static_cast<unsigned short>(ymd.year + 4800 - a); 80 0 : unsigned short m = static_cast<unsigned short>(ymd.month + 12*a - 3); 81 0 : unsigned long d = ymd.day + ((153*m + 2)/5) + 365*y + (y/4) - (y/100) + (y/400) - 32045; 82 0 : return static_cast<date_int_type>(d); 83 : } 84 : 85 : //! Convert a year-month-day into the julian day number 86 : /*! Since this implementation uses julian day internally, this is the same as the day_number. 87 : */ 88 : template<typename ymd_type_, typename date_int_type_> 89 : BOOST_DATE_TIME_INLINE 90 : date_int_type_ 91 : gregorian_calendar_base<ymd_type_,date_int_type_>::julian_day_number(const ymd_type& ymd) 92 : { 93 : return day_number(ymd); 94 : } 95 : 96 : //! Convert year-month-day into a modified julian day number 97 : /*! The day number is an absolute number of days. 98 : * MJD 0 thus started on 17 Nov 1858(Gregorian) at 00:00:00 UTC 99 : */ 100 : template<typename ymd_type_, typename date_int_type_> 101 : BOOST_DATE_TIME_INLINE 102 : date_int_type_ 103 : gregorian_calendar_base<ymd_type_,date_int_type_>::modjulian_day_number(const ymd_type& ymd) 104 : { 105 : return julian_day_number(ymd)-2400001; //prerounded 106 : } 107 : 108 : //! Change a day number into a year-month-day 109 : template<typename ymd_type_, typename date_int_type_> 110 : BOOST_DATE_TIME_INLINE 111 : ymd_type_ 112 0 : gregorian_calendar_base<ymd_type_,date_int_type_>::from_day_number(date_int_type dayNumber) 113 : { 114 0 : date_int_type a = dayNumber + 32044; 115 0 : date_int_type b = (4*a + 3)/146097; 116 0 : date_int_type c = a-((146097*b)/4); 117 0 : date_int_type d = (4*c + 3)/1461; 118 0 : date_int_type e = c - (1461*d)/4; 119 0 : date_int_type m = (5*e + 2)/153; 120 0 : unsigned short day = static_cast<unsigned short>(e - ((153*m + 2)/5) + 1); 121 0 : unsigned short month = static_cast<unsigned short>(m + 3 - 12 * (m/10)); 122 0 : year_type year = static_cast<unsigned short>(100*b + d - 4800 + (m/10)); 123 : //std::cout << year << "-" << month << "-" << day << "\n"; 124 : 125 0 : return ymd_type(static_cast<unsigned short>(year),month,day); 126 : } 127 : 128 : //! Change a day number into a year-month-day 129 : template<typename ymd_type_, typename date_int_type_> 130 : BOOST_DATE_TIME_INLINE 131 : ymd_type_ 132 : gregorian_calendar_base<ymd_type_,date_int_type_>::from_julian_day_number(date_int_type dayNumber) 133 : { 134 : date_int_type a = dayNumber + 32044; 135 : date_int_type b = (4*a+3)/146097; 136 : date_int_type c = a - ((146097*b)/4); 137 : date_int_type d = (4*c + 3)/1461; 138 : date_int_type e = c - ((1461*d)/4); 139 : date_int_type m = (5*e + 2)/153; 140 : unsigned short day = static_cast<unsigned short>(e - ((153*m + 2)/5) + 1); 141 : unsigned short month = static_cast<unsigned short>(m + 3 - 12 * (m/10)); 142 : year_type year = static_cast<year_type>(100*b + d - 4800 + (m/10)); 143 : //std::cout << year << "-" << month << "-" << day << "\n"; 144 : 145 : return ymd_type(year,month,day); 146 : } 147 : 148 : //! Change a modified julian day number into a year-month-day 149 : template<typename ymd_type_, typename date_int_type_> 150 : BOOST_DATE_TIME_INLINE 151 : ymd_type_ 152 : gregorian_calendar_base<ymd_type_,date_int_type_>::from_modjulian_day_number(date_int_type dayNumber) { 153 : date_int_type jd = dayNumber + 2400001; //is 2400000.5 prerounded 154 : return from_julian_day_number(jd); 155 : } 156 : 157 : //! Determine if the provided year is a leap year 158 : /*! 159 : *@return true if year is a leap year, false otherwise 160 : */ 161 : template<typename ymd_type_, typename date_int_type_> 162 : BOOST_DATE_TIME_INLINE 163 : bool 164 0 : gregorian_calendar_base<ymd_type_,date_int_type_>::is_leap_year(year_type year) 165 : { 166 : //divisible by 4, not if divisible by 100, but true if divisible by 400 167 0 : return (!(year % 4)) && ((year % 100) || (!(year % 400))); 168 : } 169 : 170 : //! Calculate the last day of the month 171 : /*! Find the day which is the end of the month given year and month 172 : * No error checking is performed. 173 : */ 174 : template<typename ymd_type_, typename date_int_type_> 175 : BOOST_DATE_TIME_INLINE 176 : unsigned short 177 0 : gregorian_calendar_base<ymd_type_,date_int_type_>::end_of_month_day(year_type year, 178 : month_type month) 179 : { 180 0 : switch (month) { 181 0 : case 2: 182 0 : if (is_leap_year(year)) { 183 : return 29; 184 : } else { 185 0 : return 28; 186 : }; 187 : case 4: 188 : case 6: 189 : case 9: 190 : case 11: 191 : return 30; 192 0 : default: 193 0 : return 31; 194 : }; 195 : 196 : } 197 : 198 : //! Provide the ymd_type specification for the calandar start 199 : template<typename ymd_type_, typename date_int_type_> 200 : BOOST_DATE_TIME_INLINE 201 : ymd_type_ 202 : gregorian_calendar_base<ymd_type_,date_int_type_>::epoch() 203 : { 204 : return ymd_type(1400,1,1); 205 : } 206 : 207 : //! Defines length of a week for week calculations 208 : template<typename ymd_type_, typename date_int_type_> 209 : BOOST_DATE_TIME_INLINE 210 : unsigned short 211 : gregorian_calendar_base<ymd_type_,date_int_type_>::days_in_week() 212 : { 213 : return 7; 214 : } 215 : 216 : 217 : } } //namespace gregorian 218 : 219 :