3v4l.org

run code in 150+ php & hhvm versions
Bugs & Features
<?php namespace Fisharebest\ExtCalendar; /** * interface CalendarInterface - each calendar implementation needs to provide * these methods. * * @author Greg Roach <fisharebest@gmail.com> * @copyright (c) 2014 Greg Roach * @license This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ interface CalendarInterface { public function daysInMonth($year, $month); public function dayOfWeek($jd); public function jdToYmd($jd); public function leapYear($year); public function ymdToJd($year, $month, $day); } /** * class Calendar - generic base class for specific calendars. * * @author Greg Roach <fisharebest@gmail.com> * @copyright (c) 2014 Greg Roach * @license This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ abstract class Calendar { /** Same as PHP’s ext/calendar extension */ const PHP_CALENDAR_NAME = 'Undefined'; /** Same as PHP’s ext/calendar extension */ const PHP_CALENDAR_NUMBER = -1; /** Same as PHP’s ext/calendar extension */ const PHP_CALENDAR_SYMBOL = 'CAL_UNDEFINED'; /** See the GEDCOM specification */ const GEDCOM_CALENDAR_ESCAPE = '@#DUNKNOWN@'; /** The earliest Julian Day number that can be converted into this calendar. */ const JD_START = 1; /** The latest Julian Day number that can be converted into this calendar. */ const JD_END = 2147483647; /** The maximum number of months in any year */ const MAX_MONTHS_IN_YEAR = 12; /** The maximum number of days in any month */ const MAX_DAYS_IN_MONTH = 31; /** * The concrete class needs to provide the implementation. * * @return string[] */ protected abstract function monthNames(); /** * English names for the days of the week. * * @return string[] */ protected function dayNames() { return array( 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', ); } /** * Abbreviated English names for the days of the week. * * @return string[] */ protected function dayNamesAbbreviated() { return array( 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', ); } /** * The concrete class needs to provide the implementation. * * @param $jd */ abstract public function jdToYmd($jd); /** * The concrete class needs to provide the implementation. * * @param int $year * @param int $month * @param int $day * * @return int */ abstract public function ymdToJd($year, $month, $day); /** * Convert a Julian Day number into a calendar date. * * @param $jd * @return int[] Array of month, day and year */ public function calFromJd($jd) { $dow = $this->dayOfWeek($jd); if ($jd >= static::JD_START && $jd <= static::JD_END) { list($year, $month, $day) = $this->jdToYmd($jd); return array( 'date' => $month . '/' . $day . '/' . $year, 'month' => $month, 'day' => $day, 'year' => $year, 'dow' => $dow, 'abbrevdayname' => $this->dayNameAbbreviated($dow), 'dayname' => $this->dayName($dow), 'abbrevmonth' => $this->jdMonthNameAbbreviated($jd), 'monthname' => $this->jdMonthName($jd), ); } else { return array( 'date' => '0/0/0', 'month' => 0, 'day' => 0, 'year' => 0, 'dow' => $dow, 'abbrevdayname' => $this->dayNameAbbreviated($dow), 'dayname' => $this->dayName($dow), 'abbrevmonth' => '', 'monthname' => '', ); } } /** * Provide information about this calendar. * * @return array */ public function phpCalInfo() { return array( 'months' => $this->monthNames(), 'abbrevmonths' => $this->monthNamesAbbreviated(), 'maxdaysinmonth' => static::MAX_DAYS_IN_MONTH, 'calname' => static::PHP_CALENDAR_NAME, 'calsymbol' => static::PHP_CALENDAR_SYMBOL, ); } /** * Calculate the day of the week for a given Julian Day number. * * @param int $jd * * @return int 0=Sunday ... 6=Saturday */ public function dayOfWeek($jd) { $dow = ($jd + 1) % 7; if ($dow < 0) { return $dow + 7; } else { return $dow; } } /** * English name for a day of the week. * * @param int $dow Day of the week * * @return string */ public function dayName($dow) { $days = $this->dayNames(); return $days[$dow]; } /** * Abbreviated English name for a day of the week. * * @param int $dow Day of the week * * @return string */ public function dayNameAbbreviated($dow) { $days = $this->dayNamesAbbreviated(); return $days[$dow]; } /** * Calculate the name of a month, for a specified Julian Day number. * * @param $jd * * @return string */ public function jdMonthName($jd) { list(, $month) = $this->jdToYmd($jd); $months = $this->monthNames(); return $months[$month]; } /** * Calculate the name of a month, for a specified Julian Day number. * * @param int $jd * * @return string */ public function jdMonthNameAbbreviated($jd) { list(, $month) = $this->jdToYmd($jd); $months = $this->monthNamesAbbreviated(); return $months[$month]; } /** * Unless otherwise defined, abbreviated month names are the same as full names. * * @return string[] */ public function monthNamesAbbreviated() { return $this->monthNames(); } } /** * class JulianCalendar - calculations for the Julian calendar. * * @author Greg Roach <fisharebest@gmail.com> * @copyright (c) 2014 Greg Roach * @license This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ class JulianCalendar extends Calendar implements CalendarInterface { /** Same as PHP’s ext/calendar extension */ const PHP_CALENDAR_NAME = 'Julian'; /** Same as PHP’s ext/calendar extension */ const PHP_CALENDAR_NUMBER = 1; /** Same as PHP’s ext/calendar extension */ const PHP_CALENDAR_SYMBOL = 'CAL_JULIAN'; /** See the GEDCOM specification */ const GEDCOM_CALENDAR_ESCAPE = '@#DJULIAN@'; /** * Month lengths for regular years and leap-years. * * @var int[][] */ protected static $DAYS_IN_MONTH = array( 0 => array(1 => 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), 1 => array(1 => 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), ); /** * English month names. * * @return string[] */ public function monthNames() { return array( 1 => 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', ); } /** * Abbreviated English month names. * * @return string[] */ public function monthNamesAbbreviated() { return array( 1 => 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ); } /** * Determine whether a year is a leap year. * * @param int $year * @return bool */ public function leapYear($year) { if ($year < 0) { $year++; } return $year % 4 == 0; } /** * Convert a Julian day number into a year/month/day. * * @param $jd * * @return int[]; */ public function jdToYmd($jd) { $c = $jd + 32082; $d = (int)((4 * $c + 3) / 1461); $e = $c - (int)(1461 * $d / 4); $m = (int)((5 * $e + 2) / 153); $day = $e - (int)((153 * $m + 2) / 5) + 1; $month = $m + 3 - 12 * (int)($m / 10); $year = $d - 4800 + (int)($m / 10); if ($year < 1) { // 0=1BC, -1=2BC, etc. $year--; } return array($year, $month, $day); } /** * Convert a year/month/day into a Julian day number * * @param int $year * @param int $month * @param int $day * * @return int */ public function ymdToJd($year, $month, $day) { if ($year < 0) { // 1 B.C.E. => 0, 2 B.C.E> => 1, etc. ++$year; } $a = (int)((14 - $month) / 12); $year = $year + 4800 - $a; $month = $month + 12 * $a - 3; return $day + (int)((153 * $month + 2) / 5) + 365 * $year + (int)($year / 4) - 32083; } /** * Calculate the number of days in a month. * * @param int $year * @param int $month * * @return int */ public function daysInMonth($year, $month) { if ($year == 0 || $month < 1 || $month > 12) { return trigger_error('invalid date.', E_USER_WARNING); } else { return static::$DAYS_IN_MONTH[$this->leapYear($year)][$month]; } } /** * Get the number of days after March 21 that easter falls, for a given year. * * Uses the algorithm found in PHP’s ext/calendar/easter.c * * @param int $year * * @return int */ public function easterDays($year) { // The “golden” number $golden = 1 + $year % 19; // The “dominical” number (finding a Sunday) $dom = ($year + (int)($year / 4) + 5) % 7; if ($dom < 0) { $dom += 7; } // The uncorrected “Paschal full moon” date $pfm = (3 - 11 * $golden - 7) % 30; if ($pfm < 0) { $pfm += 30; } // The corrected “Paschal full moon” date if ($pfm == 29 || $pfm == 28 && $golden > 11) { $pfm--; } $tmp = (4 - $pfm - $dom) % 7; if ($tmp < 0) { $tmp += 7; } return $pfm + $tmp + 1; } }
based on 1fhPr
Output for 5.4.0 - 7.1.0