Chris@16: /* Copyright (c) 2002,2003 CrystalClear Software, Inc. Chris@16: * Use, modification and distribution is subject to the Chris@16: * Boost Software License, Version 1.0. (See accompanying Chris@16: * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) Chris@16: * Author: Jeff Garland, Bart Garst Chris@101: * $Date$ Chris@16: */ Chris@16: Chris@16: #ifndef NO_BOOST_DATE_TIME_INLINE Chris@16: #undef BOOST_DATE_TIME_INLINE Chris@16: #define BOOST_DATE_TIME_INLINE inline Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: namespace date_time { Chris@16: //! Return the day of the week (0==Sunday, 1==Monday, etc) Chris@16: /*! Converts a year-month-day into a day of the week number Chris@16: */ Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: unsigned short Chris@16: gregorian_calendar_base::day_of_week(const ymd_type& ymd) { Chris@16: unsigned short a = static_cast((14-ymd.month)/12); Chris@16: unsigned short y = static_cast(ymd.year - a); Chris@16: unsigned short m = static_cast(ymd.month + 12*a - 2); Chris@16: unsigned short d = static_cast((ymd.day + y + (y/4) - (y/100) + (y/400) + (31*m)/12) % 7); Chris@16: //std::cout << year << "-" << month << "-" << day << " is day: " << d << "\n"; Chris@16: return d; Chris@16: } Chris@16: Chris@16: //!Return the iso week number for the date Chris@16: /*!Implements the rules associated with the iso 8601 week number. Chris@16: Basically the rule is that Week 1 of the year is the week that contains Chris@16: January 4th or the week that contains the first Thursday in January. Chris@16: Reference for this algorithm is the Calendar FAQ by Claus Tondering, April 2000. Chris@16: */ Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: int Chris@16: gregorian_calendar_base::week_number(const ymd_type& ymd) { Chris@16: unsigned long julianbegin = julian_day_number(ymd_type(ymd.year,1,1)); Chris@16: unsigned long juliantoday = julian_day_number(ymd); Chris@16: unsigned long day = (julianbegin + 3) % 7; Chris@16: unsigned long week = (juliantoday + day - julianbegin + 4)/7; Chris@16: Chris@16: if ((week >= 1) && (week <= 52)) { Chris@16: return week; Chris@16: } Chris@16: Chris@16: if (week == 53) { Chris@16: if((day==6) ||(day == 5 && is_leap_year(ymd.year))) { Chris@16: return week; //under these circumstances week == 53. Chris@16: } else { Chris@16: return 1; //monday - wednesday is in week 1 of next year Chris@16: } Chris@16: } Chris@16: //if the week is not in current year recalculate using the previous year as the beginning year Chris@16: else if (week == 0) { Chris@16: julianbegin = julian_day_number(ymd_type(static_cast(ymd.year-1),1,1)); Chris@16: juliantoday = julian_day_number(ymd); Chris@16: day = (julianbegin + 3) % 7; Chris@16: week = (juliantoday + day - julianbegin + 4)/7; Chris@16: return week; Chris@16: } Chris@16: Chris@16: return week; //not reachable -- well except if day == 5 and is_leap_year != true Chris@16: Chris@16: } Chris@16: Chris@16: //! Convert a ymd_type into a day number Chris@16: /*! The day number is an absolute number of days since the start of count Chris@16: */ Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: date_int_type_ Chris@16: gregorian_calendar_base::day_number(const ymd_type& ymd) Chris@16: { Chris@16: unsigned short a = static_cast((14-ymd.month)/12); Chris@16: unsigned short y = static_cast(ymd.year + 4800 - a); Chris@16: unsigned short m = static_cast(ymd.month + 12*a - 3); Chris@16: unsigned long d = ymd.day + ((153*m + 2)/5) + 365*y + (y/4) - (y/100) + (y/400) - 32045; Chris@16: return d; Chris@16: } Chris@16: Chris@16: //! Convert a year-month-day into the julian day number Chris@16: /*! Since this implementation uses julian day internally, this is the same as the day_number. Chris@16: */ Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: date_int_type_ Chris@16: gregorian_calendar_base::julian_day_number(const ymd_type& ymd) Chris@16: { Chris@16: return day_number(ymd); Chris@16: } Chris@16: Chris@16: //! Convert year-month-day into a modified julian day number Chris@16: /*! The day number is an absolute number of days. Chris@16: * MJD 0 thus started on 17 Nov 1858(Gregorian) at 00:00:00 UTC Chris@16: */ Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: date_int_type_ Chris@16: gregorian_calendar_base::modjulian_day_number(const ymd_type& ymd) Chris@16: { Chris@16: return julian_day_number(ymd)-2400001; //prerounded Chris@16: } Chris@16: Chris@16: //! Change a day number into a year-month-day Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: ymd_type_ Chris@16: gregorian_calendar_base::from_day_number(date_int_type dayNumber) Chris@16: { Chris@16: date_int_type a = dayNumber + 32044; Chris@16: date_int_type b = (4*a + 3)/146097; Chris@16: date_int_type c = a-((146097*b)/4); Chris@16: date_int_type d = (4*c + 3)/1461; Chris@16: date_int_type e = c - (1461*d)/4; Chris@16: date_int_type m = (5*e + 2)/153; Chris@16: unsigned short day = static_cast(e - ((153*m + 2)/5) + 1); Chris@16: unsigned short month = static_cast(m + 3 - 12 * (m/10)); Chris@16: year_type year = static_cast(100*b + d - 4800 + (m/10)); Chris@16: //std::cout << year << "-" << month << "-" << day << "\n"; Chris@16: Chris@16: return ymd_type(static_cast(year),month,day); Chris@16: } Chris@16: Chris@16: //! Change a day number into a year-month-day Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: ymd_type_ Chris@16: gregorian_calendar_base::from_julian_day_number(date_int_type dayNumber) Chris@16: { Chris@16: date_int_type a = dayNumber + 32044; Chris@16: date_int_type b = (4*a+3)/146097; Chris@16: date_int_type c = a - ((146097*b)/4); Chris@16: date_int_type d = (4*c + 3)/1461; Chris@16: date_int_type e = c - ((1461*d)/4); Chris@16: date_int_type m = (5*e + 2)/153; Chris@16: unsigned short day = static_cast(e - ((153*m + 2)/5) + 1); Chris@16: unsigned short month = static_cast(m + 3 - 12 * (m/10)); Chris@16: year_type year = static_cast(100*b + d - 4800 + (m/10)); Chris@16: //std::cout << year << "-" << month << "-" << day << "\n"; Chris@16: Chris@16: return ymd_type(year,month,day); Chris@16: } Chris@16: Chris@16: //! Change a modified julian day number into a year-month-day Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: ymd_type_ Chris@16: gregorian_calendar_base::from_modjulian_day_number(date_int_type dayNumber) { Chris@16: date_int_type jd = dayNumber + 2400001; //is 2400000.5 prerounded Chris@16: return from_julian_day_number(jd); Chris@16: } Chris@16: Chris@16: //! Determine if the provided year is a leap year Chris@16: /*! Chris@16: *@return true if year is a leap year, false otherwise Chris@16: */ Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: bool Chris@16: gregorian_calendar_base::is_leap_year(year_type year) Chris@16: { Chris@16: //divisible by 4, not if divisible by 100, but true if divisible by 400 Chris@16: return (!(year % 4)) && ((year % 100) || (!(year % 400))); Chris@16: } Chris@16: Chris@16: //! Calculate the last day of the month Chris@16: /*! Find the day which is the end of the month given year and month Chris@16: * No error checking is performed. Chris@16: */ Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: unsigned short Chris@16: gregorian_calendar_base::end_of_month_day(year_type year, Chris@16: month_type month) Chris@16: { Chris@16: switch (month) { Chris@16: case 2: Chris@16: if (is_leap_year(year)) { Chris@16: return 29; Chris@16: } else { Chris@16: return 28; Chris@16: }; Chris@16: case 4: Chris@16: case 6: Chris@16: case 9: Chris@16: case 11: Chris@16: return 30; Chris@16: default: Chris@16: return 31; Chris@16: }; Chris@16: Chris@16: } Chris@16: Chris@16: //! Provide the ymd_type specification for the calandar start Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: ymd_type_ Chris@16: gregorian_calendar_base::epoch() Chris@16: { Chris@16: return ymd_type(1400,1,1); Chris@16: } Chris@16: Chris@16: //! Defines length of a week for week calculations Chris@16: template Chris@16: BOOST_DATE_TIME_INLINE Chris@16: unsigned short Chris@16: gregorian_calendar_base::days_in_week() Chris@16: { Chris@16: return 7; Chris@16: } Chris@16: Chris@16: Chris@16: } } //namespace gregorian Chris@16: Chris@16: