/* 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: 2010-01-10 14:17:23 -0500 (Sun, 10 Jan 2010) $
 */

#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 week;
    }

    if ((week == 53)) {
      if((day==6) ||(day == 5 && is_leap_year(ymd.year))) {
        return 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 week;
    }

    return 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 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


