Calculates Gregorian and Julian calendar dates from the Julian Day number
(jdn) for the period since jdn=-34839655 (i.e. the year -100100 of both
calendars) to some millions years ahead of the present.

@param $julianDayNumber

@return array
492339
protected static function julian2georgian($julianDayNumber) {
        
        $j = 4 * $julianDayNumber + 139361631;
        $j += self::division(self::division(4 * $julianDayNumber + 183187720, 146097) * 3, 4) * 4 - 3908;
        $i = self::division(($j % 1461), 4) * 5 + 308;
        
        $gDay   = self::division(($i % 153), 5) + 1;
        $gMonth = (self::division($i, 153) % 12) + 1;
        $gYear  = self::division($j, 1461) - 100100 + self::division(8 - $gMonth, 6);
        
        return [$gYear, $gMonth, $gDay];
    }
593077
protected function jdToY($julian_day)
    {
        // Estimate the year, and underestimate it, it will be refined after
        $year = max((int) ((($julian_day - 347998) * 98496) / 35975351) - 1, 1);

        // Adjust by adding years;
        while ($julian_day >= $this->yToJd($year + 1)) {
            $year++;
        }

        return $year;
    }
860997
public function daysBetween(Date $other) : int
    {
        return $this->dateTime->diff($other->dateTime, true)->days;
    }
631335
protected static function getDayOfYear($day, $month) {
        
        $dayOfYear = $day;
        if ($month > 6) {
            $dayOfYear += (186 + (($month - 6 - 1) * 30));
        } else {
            $dayOfYear += (($month - 1) * 31);
        }
        
        return $dayOfYear;
    }
996269
private function convertTodayToHijri()
    {
        list($arYear, $arMonth, $arDay) = (new Date())->hjConvert(date('Y'), date('m'), date('d'));
        
        return [
            'arYear'  => $arYear,
            'arMonth' => $arMonth,
            'arDay'   => $arDay,
        ];
    }
1136619
public static void jdToCE(int julianDay, int jdEpochOffset, int[] fields) {
        int c4; // number of 4 year cycle (1461 days)
        int[] r4 = new int[1]; // remainder of 4 year cycle, always positive

        c4 = floorDivide(julianDay - jdEpochOffset, 1461, r4);

        // exteded year
        fields[0] = 4 * c4 + (r4[0]/365 - r4[0]/1460); // 4 * <number of 4year cycle> + <years within the last cycle>

        int doy = (r4[0] == 1460) ? 365 : (r4[0] % 365); // days in present year

        // month
        fields[1] = doy / 30; // 30 -> Coptic/Ethiopic month length up to 12th month
        // day
        fields[2] = (doy % 30) + 1; // 1-based days in a month
    }
1261802
private static int[] jdToGregorian(double jd) {
       double JULIAN_EPOCH = 1721425.5;
       double wjd, depoch, quadricent, dqc, cent, dcent, quad, dquad, yindex, yearday, leapadj;
       int year, month, day;
       
       wjd = Math.floor(jd - 0.5) + 0.5;
       depoch = wjd - JULIAN_EPOCH;
       quadricent = Math.floor(depoch / 146097);
       dqc = depoch % 146097;
       cent = Math.floor(dqc / 36524);
       dcent = dqc % 36524;
       quad = Math.floor(dcent / 1461);
       dquad = dcent % 1461;
       yindex = Math.floor(dquad / 365);
       year = (int)((quadricent * 400) + (cent * 100) + (quad * 4) + yindex);
       
       if (!((cent == 4) || (yindex == 4))) {
          year++;
       }
       
       yearday = wjd - gregorianToJD(year, 1, 1);
       leapadj = ((wjd < gregorianToJD(year, 3, 1)) ? 0
             :
             (isGregorianLeap(year) ? 1 : 2)
             );
       
       month = (int)Math.floor((((yearday + leapadj) * 12) + 373) / 367);
       day = (int)(wjd - gregorianToJD(year, month, 1)) + 1;

       int[] julianDate = new int[3];
       
       julianDate[0] = year;
       julianDate[1] = month;
       julianDate[2] = day;
       
       return julianDate;
    }
1163204
private function getDay($dayNumber)
    {
        return isset($this->days[$dayNumber]) ? $this->days[$dayNumber] : null;
    }
313184
public static function hijriToJulian(int $year, int $month, int $day)
    {
        return floor((11 * $year + 3) / 30) + floor(354 * $year) + floor(30 * $month)
            - floor(($month - 1) / 2) + $day + 1948440 - 386;
    }
1214768
public static function getDaysByMonthsOfYear($year = null): array
    {
        $year = $year ? $year : date('Y');
        $months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
        if (self::isLeapYear($year)) $months [1] = 29;
        return $months;
    }
1130908
def julian(mon, day, year):
    
    ig = 15 + 31 * (10 + 12 * 1582)
    if year == 0:
        print("Julian no can do")
        return
    if year < 0:
        year = year + 1
    if mon > 2:
        julian_year = year
        julian_month = mon + 1
    else:
        julian_year = year - 1
        julian_month = mon + 13
    j1 = int(365.25 * julian_year)
    j2 = int(30.6001 * julian_month)
    j3 = day + 1720995
    julian_day = j1 + j2 + j3
    if day + 31 * (mon + 12 * year) >= ig:
        jadj = int(0.01 * julian_year)
        julian_day = julian_day + 2 - jadj + int(0.25 * jadj)
    return julian_day
386969
private static function jdMonthNameCalendar(CalendarInterface $calendar, $julian_day, $months)
    {
        list(, $month) = $calendar->jdToYmd($julian_day);

        return $months[$month];
    }
459135
public static function easterDate($year)
    {
        if ($year < 1970 || $year > 2037) {
            return trigger_error('This function is only valid for years between 1970 and 2037 inclusive', E_USER_WARNING);
        }

        $days = self::$gregorian_calendar->easterDays($year);

        // Calculate time-zone offset
        $date_time      = new \DateTime('now', new \DateTimeZone(date_default_timezone_get()));
        $offset_seconds = (int) $date_time->format('Z');

        if ($days < 11) {
            return self::jdtounix(self::$gregorian_calendar->ymdToJd($year, 3, $days + 21)) - $offset_seconds;
        } else {
            return self::jdtounix(self::$gregorian_calendar->ymdToJd($year, 4, $days - 10)) - $offset_seconds;
        }
    }
348279
public static function FormattedPHPToExcel($year, $month, $day, $hours = 0, $minutes = 0, $seconds = 0)
    {
        if (self::$excelBaseDate == self::CALENDAR_WINDOWS_1900) {
            //
            //    Fudge factor for the erroneous fact that the year 1900 is treated as a Leap Year in MS Excel
            //    This affects every date following 28th February 1900
            //
            $excel1900isLeapYear = true;
            if (($year == 1900) && ($month <= 2)) {
                $excel1900isLeapYear = false;
            }
            $myexcelBaseDate = 2415020;
        } else {
            $myexcelBaseDate = 2416481;
            $excel1900isLeapYear = false;
        }

        //    Julian base date Adjustment
        if ($month > 2) {
            $month -= 3;
        } else {
            $month += 9;
            --$year;
        }

        //    Calculate the Julian Date, then subtract the Excel base date (JD 2415020 = 31-Dec-1899 Giving Excel Date of 0)
        $century = substr($year, 0, 2);
        $decade = substr($year, 2, 2);
        $excelDate = floor((146097 * $century) / 4) + floor((1461 * $decade) / 4) + floor((153 * $month + 2) / 5) + $day + 1721119 - $myexcelBaseDate + $excel1900isLeapYear;

        $excelTime = (($hours * 3600) + ($minutes * 60) + $seconds) / 86400;

        return (float) $excelDate + $excelTime;
    }
508184
public function convert_to_timestamp($year, $month, $day, $hour = 0, $minute = 0) {
        $gregorianinfo = $this->convert_to_gregorian($year, $month, $day, $hour, $minute);
        return make_timestamp(
            $gregorianinfo['year'],
            $gregorianinfo['month'],
            $gregorianinfo['day'],
            $gregorianinfo['hour'],
            $gregorianinfo['minute'],
            0);
    }
1347255
private function getClosestDayAfter($dayNumber)
    {
        if (null !== $day = $this->getDay($dayNumber)) {
            return $day;
        }

        return $this->getDayAfter($dayNumber);
    }
1369959
public static function jdToGregorian($julian_day)
    {
        // PHP has different limits on 32 and 64 bit systems.
        $MAX_JD = PHP_INT_SIZE == 4 ? 536838866 : 2305843009213661906;

        return self::jdToCalendar(self::$gregorian_calendar, $julian_day, 1, $MAX_JD);
    }