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