/**
 * Calculates the day of the year for a given date
 *
 * @param   int    $year  The year, for example: 2000, -1000, 0
 * @param   int    $month The month, from 1 to 12
 * @param   float  $day   The day, from 1 to 31, or with decimals
 * @return  int           The day of the year, for example: 1, 2, 365, 366
 */
function aa_date_to_day_of_year($year, $month, $day)
{
    if (aa_is_leap_year($year)) {
        $K = 1;
    } else {
        $K = 2;
    }
    $day_of_year = aa_int(275 * $month / 9) - $K * aa_int(($month + 9) / 12) + $day - 30;
    return $day_of_year;
}
/**
 * Calculates the Julian day of a date in the Julian calendar
 *
 * This algorithm is invalid for negative Julian days.
 *
 * @param  int      $year  The year, for example: 2000, -1000, 0
 * @param  int      $month The month, from 1 to 12
 * @param  float    $day   The day, from 1 to 31, or with decimals
 * @return int|bool        The Julian day, or false on error
 */
function aa_julian_date_to_julian_day($year, $month, $day)
{
    if ($month <= 2) {
        $year--;
        $month += 12;
    }
    $julian_day = aa_int(365.25 * ($year + 4716)) + aa_int(30.6001 * ($month + 1)) + $day - 1524.5;
    if ($julian_day < 0) {
        aa_set_error('This algorithm is invalid for negative Julian days.');
        return false;
    }
    return $julian_day;
}
/**
 * Calculates the date for a given day in a given year
 *
 * The calendar in which the year falls is automatically detected.
 * This is needed to determine if the year is a leap year.
 *
 * @param   int        $year        The year, for example: 2000, -1000, 0
 * @param   int        $day_of_year The day of the year, for example: 1, 2, 365, 366
 * @return  array|bool              The date or false on error
 * @returns int        0            The year
 * @returns int        1            The month
 * @returns int        2            The day
 */
function aa_day_of_year_to_date($year, $day_of_year)
{
    if (aa_is_leap_year($year)) {
        $K = 1;
    } else {
        $K = 2;
    }
    if ($day_of_year < 32) {
        $month = 1;
    } else {
        $month = aa_int(($K + $day_of_year) * 9 / 275 + 0.98);
    }
    $day = $day_of_year - aa_int(275 * $month / 9) + $K * aa_int(($month + 9) / 12) + 30;
    return array($year, $month, $day);
}
/**
 * Calculates the date from a Julian day
 *
 * The calendar in which the date falls is automatically detected.
 * This algorithm is invalid for negative Julian days.
 *
 * @param   int        $julian_day The Julian day
 * @return  array|bool             The date or false on error
 * @returns int        0           The year
 * @returns int        1           The month
 * @returns float      2           The day
 */
function aa_julian_day_to_date($julian_day)
{
    if ($julian_day < 0) {
        aa_set_error('This algorithm is invalid for negative Julian days.');
        return false;
    }
    $julian_day += 0.5;
    $Z = aa_int($julian_day);
    $F = $julian_day - $Z;
    // fixes Meeus original algorithm (p. 63) to calculate the Julian day of the change of calendar
    // the value of 2299161 is the Julian day for 1582-10-15 in the Gregorian calendar + 0.5
    // 1582-10-15 is the default first day of the Gregorian calendar
    list($change_year, $change_month, $change_day) = aa_get_calendar_change_date();
    $change_julian_day = aa_gregorian_date_to_julian_day($change_year, $change_month, $change_day);
    $change_julian_day += 0.5;
    if ($Z < $change_julian_day) {
        $A = $Z;
    } else {
        $alpha = aa_int(($Z - 1867216.25) / 36524.25);
        $A = $Z + 1 + $alpha - aa_int($alpha / 4);
    }
    $B = $A + 1524;
    $C = aa_int(($B - 122.1) / 365.25);
    $D = aa_int(365.25 * $C);
    $E = aa_int(($B - $D) / 30.6001);
    $day = $B - $D - aa_int(30.6001 * $E) + $F;
    if ($E < 14) {
        $month = $E - 1;
    } else {
        if ($E == 14 or $E == 15) {
            $month = $E - 13;
        } else {
            aa_set_error('The calculated value of the month is out of range.');
            return false;
        }
    }
    if ($month > 2) {
        $year = $C - 4716;
    } else {
        $year = $C - 4715;
    }
    return array($year, $month, $day);
}