/*
 * CALFAQ version 1.1, 4 April 2008
 *
 * COPYRIGHT:
 *   These functions are Copyright (c) 2008 by Claus Tondering
 *   (claus@tondering.dk).
 *  
 * LICENSE:
 *   The code is distributed under the Boost Software License, which
 *   says:
 *  
 *     Boost Software License - Version 1.0 - August 17th, 2003
 *  
 *     Permission is hereby granted, free of charge, to any person or
 *     organization obtaining a copy of the software and accompanying
 *     documentation covered by this license (the "Software") to use,
 *     reproduce, display, distribute, execute, and transmit the
 *     Software, and to prepare derivative works of the Software, and
 *     to permit third-parties to whom the Software is furnished to do
 *     so, all subject to the following:
 *  
 *     The copyright notices in the Software and this entire
 *     statement, including the above license grant, this restriction
 *     and the following disclaimer, must be included in all copies of
 *     the Software, in whole or in part, and all derivative works of
 *     the Software, unless such copies or derivative works are solely
 *     in the form of machine-executable object code generated by a
 *     source language processor.
 *  
 *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
 *     NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
 *     ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
 *     OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 *     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 *     USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * DESCRIPTION:
 *   These functions are an implementation in the C language of the
 *   formulas presented in the Calendar FAQ at
 *   http://www.tondering.dk/claus/calendar.html.
 *
 *   The implementation follows the formulas mentioned in version 2.9
 *   of the FAQ quite closely. The focus of the implementation is on
 *   simplicity and clarity. For this reason, no complex data
 *   structures or classes are used, nor has any attempt been made to
 *   optimize the code. Also, no verification of the input parameters
 *   is performed (except in the function simple_gregorian_easter).
 *
 *   All numbers (including Julian Day Numbers which current have
 *   values of almost 2,500,000) are assumed to be representable as
 *   variables of type 'int'.
 */

/*
 * Calendar styles
 */
#define JULIAN    0
#define GREGORIAN 1


/*
 * is_leap:
 * Determines if a year is a leap year.
 * Input parameters:
 *     Calendar style (JULIAN or GREGORIAN)
 *     Year (must be >0)
 * Returns:
 *     1 if the year is a leap year, 0 otherwise.
 *
 * Note: The algorithm assumes that AD 4 is a leap year. This may be
 * historically inaccurate. See the FAQ.
 *
 * Reference: Sections 2.1.1 and 2.2.1 of version 2.9 of the FAQ.
 */
int is_leap(int style, int year);


/*
 * days_in_month:
 * Calculates the number of days in a month.
 * Input parameters:
 *     Calendar style (JULIAN or GREGORIAN)
 *     Year (must be >0)
 *     Month (1..12)
 * Returns:
 *     The number of days in the month (28..31)
 */
int days_in_month(int style, int year, int month);


/*
 * solar_number:
 * Calculates the Solar Number of a given year.
 * Input parameter:
 *     Year (must be >0)
 * Returns:
 *     Solar Number (1..28)
 *
 * Reference: Section 2.4 of version 2.9 of the FAQ.
 */
int solar_number(int year);


/*
 * day_of_week:
 * Calculates the weekday for a given date.
 * Input parameters:
 *     Calendar style (JULIAN or GREGORIAN)
 *     Year (must be >0)
 *     Month (1..12)
 *     Day (1..31)
 * Returns:
 *     0 for Sunday, 1 for Monday, 2 for Tuesday, etc.
 *
 * Reference: Section 2.6 of version 2.9 of the FAQ.
 */
int day_of_week(int style, int year, int month, int day);


/*
 * golden_number:
 * Calculates the Golden Number of a given year.
 * Input parameter:
 *     Year (must be >0)
 * Returns:
 *     Golden Number (1..19)
 *
 * Reference: Section 2.13.3 of version 2.9 of the FAQ.
 */
int golden_number(int year);


/*
 * epact:
 * Calculates the Epact of a given year.
 * Input parameters:
 *     Calendar style (JULIAN or GREGORIAN)
 *     Year (must be >0)
 * Returns:
 *     Epact (1..30)
 *
 * Reference: Section 2.13.5 of version 2.9 of the FAQ.
 */
int epact(int style, int year);


/*
 * paschal_full_moon:
 * Calculates the date of the Paschal full moon.
 * Input parameters:
 *     Calendar style (JULIAN or GREGORIAN)
 *     Year (must be >0)
 * Output parameters:
 *     Address of month of Paschal full moon (3..4)
 *     Address of day of Pascal full moon (1..31)
 *
 * Reference: Section 2.13.4 and 2.13.6 of version 2.9 of the FAQ.
 */
void paschal_full_moon(int style, int year, int *month, int *day);


/*
 * easter:
 * Calculates the date of Easter Sunday.
 * Input parameters:
 *     Calendar style (JULIAN or GREGORIAN)
 *     Year (must be >0)
 * Output parameters:
 *     Address of month of Easter Sunday (3..4)
 *     Address of day of Easter Sunday (1..31)
 *
 * Reference: Section 2.13.7 of version 2.9 of the FAQ.
 */
void easter(int style, int year, int *month, int *day);


/*
 * simple_gregorian_easter:
 * Calculates the date of Easter Sunday in the Gregorian calendar.
 * Input parameter:
 *     Year (must be in the range 1900..2099)
 * Output parameters:
 *     Address of month of Easter Sunday (3..4)
 *     Address of day of Easter Sunday (1..31)
 *
 * If the year is outside the legal range, *month is set to zero.
 *
 * Reference: Section 2.13.8 of version 2.9 of the FAQ.
 */
void simple_gregorian_easter(int year, int *month, int *day);


/*
 * indiction:
 * Calculates the Indiction of a given year.
 * Input parameter:
 *     Year (must be >0)
 * Returns:
 *     Indiction (1..15)
 *
 * Reference: Section 2.15 of version 2.9 of the FAQ.
 */
int indiction(int year);


/*
 * julian_period:
 * Calculates the year in the Julian Period corresponding to a given
 * year.
 * Input parameter:
 *    Year (must be in the range -4712..3267). The year 1 BC must be
 *        given as 0, the year 2 BC must be given as -1, etc.
 * Returns:
 *    The corresponding year in the Julian period
 *
 * Reference: Section 2.16 of version 2.9 of the FAQ.
 */
int julian_period(int year);


/*
 * date_to_jdn:
 * Calculates the Julian Day Number for a given date.
 * Input parameters:
 *     Calendar style (JULIAN or GREGORIAN)
 *     Year (must be > -4800). The year 1 BC must be given as 0, the
 *         year 2 BC must be given as -1, etc.
 *     Month (1..12)
 *     Day (1..31)
 * Returns:
 *     Julian Day Number
 *
 * Reference: Section 2.16.1 of version 2.9 of the FAQ.
 */
int date_to_jdn(int style, int year, int month, int day);
    

/*
 * jdn_to_date:
 * Calculates the date for a given Julian Day Number.
 * Input parameter:
 *     Calendar style (JULIAN or GREGORIAN)
 *     Julian Day Number
 * Output parameters:
 *     Address of year. The year 1 BC will be stored as 0, the year
 *         2 BC will be stored as -1, etc.
 *     Address of month (1..12)
 *     Address of day (1..31)
 *
 * Reference: Section 2.16.1 of version 2.9 of the FAQ.
 */
void jdn_to_date(int style, int JD, int *year, int *month, int *day);


/*
 * week_number:
 * Calculates the ISO 8601 week number (and corresponding year) for a given
 * Gregorian date.
 * Input parameters:
 *     Year (must be >0)
 *     Month (1..12)
 *     Day
 * Output parameters:
 *     Address of week number (1..53)
 *     Address of corresponding year
 *
 * Reference: Section 7.8 of version 2.9 of the FAQ.
 */
void week_number(int year, int month, int day, int *week_number, int *week_year);
