diff options
| author | Greg Roach <fisharebest@gmail.com> | 2014-09-27 11:53:26 +0100 |
|---|---|---|
| committer | Greg Roach <fisharebest@gmail.com> | 2014-09-27 11:53:26 +0100 |
| commit | c6632115071fe05bb61f928bdd2f55c1bb9710a7 (patch) | |
| tree | 036eaea8ce229861c1028a8e7a713ee92c580ac5 /library | |
| parent | 642234aceed964c944e64cc74d9368093a26a33a (diff) | |
| download | webtrees-c6632115071fe05bb61f928bdd2f55c1bb9710a7.tar.gz webtrees-c6632115071fe05bb61f928bdd2f55c1bb9710a7.tar.bz2 webtrees-c6632115071fe05bb61f928bdd2f55c1bb9710a7.zip | |
Upgrade fishareest/ext-calendar to 1.2.0
Diffstat (limited to 'library')
18 files changed, 789 insertions, 851 deletions
diff --git a/library/WT/Date/Calendar.php b/library/WT/Date/Calendar.php index 63132cb11b..d55d1a832e 100644 --- a/library/WT/Date/Calendar.php +++ b/library/WT/Date/Calendar.php @@ -101,7 +101,7 @@ class WT_Date_Calendar { } function isLeapYear() { - return $this->calendar->leapYear($this->y); + return $this->calendar->isLeapYear($this->y); } // Set the object’s JD from a potentially incomplete YMD diff --git a/library/autoload.php b/library/autoload.php index 771eec2dff..9638441536 100644 --- a/library/autoload.php +++ b/library/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInitdc53286047dab341fdf097ef0c616c7d::getLoader(); +return ComposerAutoloaderInite0030dcce627568b0e84276091dd1df6::getLoader(); diff --git a/library/composer/autoload_classmap.php b/library/composer/autoload_classmap.php index 2eb14c7109..763f3c0e27 100644 --- a/library/composer/autoload_classmap.php +++ b/library/composer/autoload_classmap.php @@ -7,8 +7,8 @@ $baseDir = dirname($vendorDir); return array( 'Datamatrix' => $vendorDir . '/tecnick.com/tcpdf/include/barcodes/datamatrix.php', + 'Fisharebest\\ExtCalendar\\AbstractCalendar' => $vendorDir . '/fisharebest/ext-calendar/src/AbstractCalendar.php', 'Fisharebest\\ExtCalendar\\ArabicCalendar' => $vendorDir . '/fisharebest/ext-calendar/src/ArabicCalendar.php', - 'Fisharebest\\ExtCalendar\\Calendar' => $vendorDir . '/fisharebest/ext-calendar/src/Calendar.php', 'Fisharebest\\ExtCalendar\\CalendarInterface' => $vendorDir . '/fisharebest/ext-calendar/src/CalendarInterface.php', 'Fisharebest\\ExtCalendar\\FrenchCalendar' => $vendorDir . '/fisharebest/ext-calendar/src/FrenchCalendar.php', 'Fisharebest\\ExtCalendar\\GregorianCalendar' => $vendorDir . '/fisharebest/ext-calendar/src/GregorianCalendar.php', @@ -2419,10 +2419,10 @@ return array( 'Zend_Tag_Taggable' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Tag/Taggable.php', 'Zend_Test_DbAdapter' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/DbAdapter.php', 'Zend_Test_DbStatement' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/DbStatement.php', - 'Zend_Test_PHPUnit_Constraint_DomQuery' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/PHPUnit/Constraint/DomQuery34.php', + 'Zend_Test_PHPUnit_Constraint_DomQuery' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/PHPUnit/Constraint/DomQuery41.php', 'Zend_Test_PHPUnit_Constraint_Exception' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/PHPUnit/Constraint/Exception.php', 'Zend_Test_PHPUnit_Constraint_Redirect' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/PHPUnit/Constraint/Redirect34.php', - 'Zend_Test_PHPUnit_Constraint_ResponseHeader' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/PHPUnit/Constraint/ResponseHeader34.php', + 'Zend_Test_PHPUnit_Constraint_ResponseHeader' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/PHPUnit/Constraint/ResponseHeader37.php', 'Zend_Test_PHPUnit_ControllerTestCase' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/PHPUnit/ControllerTestCase.php', 'Zend_Test_PHPUnit_DatabaseTestCase' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/PHPUnit/DatabaseTestCase.php', 'Zend_Test_PHPUnit_Db_Connection' => $vendorDir . '/bombayworks/zendframework1/library/Zend/Test/PHPUnit/Db/Connection.php', diff --git a/library/composer/autoload_real.php b/library/composer/autoload_real.php index 2f78fd1f4c..44113db005 100644 --- a/library/composer/autoload_real.php +++ b/library/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitdc53286047dab341fdf097ef0c616c7d +class ComposerAutoloaderInite0030dcce627568b0e84276091dd1df6 { private static $loader; @@ -19,9 +19,9 @@ class ComposerAutoloaderInitdc53286047dab341fdf097ef0c616c7d return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInitdc53286047dab341fdf097ef0c616c7d', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInite0030dcce627568b0e84276091dd1df6', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInitdc53286047dab341fdf097ef0c616c7d', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInite0030dcce627568b0e84276091dd1df6', 'loadClassLoader')); $includePaths = require __DIR__ . '/include_paths.php'; array_push($includePaths, get_include_path()); @@ -46,14 +46,14 @@ class ComposerAutoloaderInitdc53286047dab341fdf097ef0c616c7d $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequiredc53286047dab341fdf097ef0c616c7d($file); + composerRequiree0030dcce627568b0e84276091dd1df6($file); } return $loader; } } -function composerRequiredc53286047dab341fdf097ef0c616c7d($file) +function composerRequiree0030dcce627568b0e84276091dd1df6($file) { require $file; } diff --git a/library/composer/installed.json b/library/composer/installed.json index 68099ded59..a9186e8ef6 100644 --- a/library/composer/installed.json +++ b/library/composer/installed.json @@ -386,32 +386,27 @@ }, { "name": "fisharebest/ext-calendar", - "version": "1.1.2", - "version_normalized": "1.1.2.0", + "version": "1.2.0", + "version_normalized": "1.2.0.0", "source": { "type": "git", "url": "https://github.com/fisharebest/ext-calendar.git", - "reference": "6ba593dd58de9964f456df0b388e77df1bce22a1" + "reference": "e73e382d347440c9ea6ac8abc658cc4405c9250d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fisharebest/ext-calendar/zipball/6ba593dd58de9964f456df0b388e77df1bce22a1", - "reference": "6ba593dd58de9964f456df0b388e77df1bce22a1", + "url": "https://api.github.com/repos/fisharebest/ext-calendar/zipball/e73e382d347440c9ea6ac8abc658cc4405c9250d", + "reference": "e73e382d347440c9ea6ac8abc658cc4405c9250d", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "ext-calendar": "*", - "ext-mbstring": "*", "phpunit/phpunit": "*", "satooshi/php-coveralls": "dev-master" }, - "suggest": { - "patchwork/utf8": "ext/mb_string support is required to generate dates using Hebrew text." - }, - "time": "2014-09-16 06:20:56", + "time": "2014-09-27 08:43:30", "type": "library", "installation-source": "dist", "autoload": { @@ -430,18 +425,23 @@ "role": "Developer" } ], - "description": "Implementation of various calendars, plus PHP shims for the ext/calendar extension", + "description": "Implementation of the Arabic (Hijri), French, Gregorian, Jewish, Julian and Persian (Jalali) calendars. PHP shims for the ext/calendar extension.", "homepage": "https://github.com/fisharebest/ext-calendar", "keywords": [ + "Jalali", + "arabic", "calendar", "ext-calendar", "french", "gregorian", "hebrew", + "hijri", "jewish", "julian", "julian day", - "julian day number" + "julian day number", + "persian", + "shamsi" ] } ] diff --git a/library/fisharebest/ext-calendar/CHANGELOG.md b/library/fisharebest/ext-calendar/CHANGELOG.md index 1827c8f821..04e06cdb0e 100644 --- a/library/fisharebest/ext-calendar/CHANGELOG.md +++ b/library/fisharebest/ext-calendar/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGE LOG ========== +## 1.2.0 (2014-09-27) + - Improve coverage of unit tests. + - Remove dependency on mb_string - generate Hebrew text directly in ISO-8859-8. + - Code style tips from scrutinizer-ci.com. + ## 1.1.2 (2014-09-16) - Fix #1; add support for the third parameter in jdtojewish(). diff --git a/library/fisharebest/ext-calendar/README.md b/library/fisharebest/ext-calendar/README.md index ef6cc00849..9c528c8a96 100644 --- a/library/fisharebest/ext-calendar/README.md +++ b/library/fisharebest/ext-calendar/README.md @@ -17,7 +17,7 @@ This package provides an implementation of the [shims](https://en.wikipedia.org/wiki/Shim_%28computing%29) for the [functions](https://php.net/ref.calendar) and [constants](https://php.net/calendar.constants) in PHP‘s [ext/calendar](https://php.net/calendar) extension. -It allows you to use these functions on servers that do not have the extension installed. +It allows you to use these functions on servers that do not have the extension installed (such as HHVM). * [cal_days_in_month()](https://php.net/cal_days_in_month) * [cal_from_jd()](https://php.net/cal_from_jd) @@ -59,7 +59,7 @@ If you want to create the “shim” functions, you must tell the package to cre Now you can use the PHP functions, whether `ext/calendar` is installed or not: ``` php -print_r(cal_info(CAL_GREGORIAN)); +print_r(cal_info(CAL_GREGORIAN)); // Works in HHVM! ``` Alternatively, just use the calendar classes directly. @@ -79,9 +79,8 @@ $calendar = new PersianCalendar; $julian_day = $calendar->ymdToJd($year, $month, $day); list($year, $month, $day) = $calendar->jdToYmd($julian_day); -// Information functions (see the source for more) -$is_leap_year = $calendar->leapYear($year); -$day_of_week = $calendar->dayOfWeek($julian_day); +// Information functions +$is_leap_year = $calendar->isLeapYear($year); $month_length = $calendar->daysInMonth($year, $month); ``` @@ -104,18 +103,9 @@ Thus the package always provides the same behaviour as the native `ext/calendar` * [#67976](https://bugs.php.net/bug.php?id=67976) Wrong value in `cal_days_in_month()` for French calendar - found by this project! -HHVM -==== - -The package should work on [HHVM](http://hhvm.com/). However, we can’t run the unit -tests on it, as HHVM does not (yet?) include the `ext/calendar` extension. - Development and contributions ============================= -Note that `require-dev` will require `ext-calendar`, as we use it as a reference -implementation for testing. - Due to the known restrictions above, you may need to run unit tests using `TZ=UTC phpunit`. Pull requests are welcome. Please ensure you include unit-tests where diff --git a/library/fisharebest/ext-calendar/src/AbstractCalendar.php b/library/fisharebest/ext-calendar/src/AbstractCalendar.php new file mode 100644 index 0000000000..c353fff2ab --- /dev/null +++ b/library/fisharebest/ext-calendar/src/AbstractCalendar.php @@ -0,0 +1,59 @@ +<?php +namespace Fisharebest\ExtCalendar; + +use InvalidArgumentException; + +/** + * class AbstractCalendar - 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 AbstractCalendar { + /** 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; + + /** Does the calendar start at year 1, or are we allowed negative (BCE) years. */ + const NEGATIVE_YEARS_ALLOWED = false; + + /** + * Calculate the number of days in a month. + * + * @param int $year + * @param int $month + * + * @return int + * + * @throws InvalidArgumentException + */ + public function daysInMonth($year, $month) { + if ($year == 0 || $year < 0 && !static::NEGATIVE_YEARS_ALLOWED) { + throw new InvalidArgumentException('Year ' . $year . ' is invalid for this calendar'); + } elseif ($month < 1 || $month > static::MAX_MONTHS_IN_YEAR) { + throw new InvalidArgumentException('Month ' . $month . ' is invalid for this calendar'); + } else { + return static::$DAYS_IN_MONTH[$this->isLeapYear($year)][$month]; + } + } +} diff --git a/library/fisharebest/ext-calendar/src/ArabicCalendar.php b/library/fisharebest/ext-calendar/src/ArabicCalendar.php index 55c045d36a..bfc4223a0a 100644 --- a/library/fisharebest/ext-calendar/src/ArabicCalendar.php +++ b/library/fisharebest/ext-calendar/src/ArabicCalendar.php @@ -2,7 +2,7 @@ namespace Fisharebest\ExtCalendar; /** - * class ArabicCalendar - calculations for the Arabic (Hijri) calendar. + * Class ArabicCalendar - calculations for the Arabic (Hijri) calendar. * * @author Greg Roach <fisharebest@gmail.com> * @copyright (c) 2014 Greg Roach @@ -19,25 +19,13 @@ namespace Fisharebest\ExtCalendar; * 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 ArabicCalendar extends Calendar implements CalendarInterface { - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_NAME = 'Arabic'; - - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_NUMBER = 4; // PHP uses 0-3 - - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_SYMBOL = 'CAL_ARABIC'; - +class ArabicCalendar extends AbstractCalendar implements CalendarInterface { /** See the GEDCOM specification */ const GEDCOM_CALENDAR_ESCAPE = '@#DHIJRI@'; /** The earliest Julian Day number that can be converted into this calendar. */ const JD_START = 1948440; // 1 Muharram 1 AH = 16 JUL 0622 (Julian) - /** The maximum number of days in any month */ - const MAX_DAYS_IN_MONTH = 30; - /** * Month lengths for regular years and leap-years. * @@ -54,21 +42,21 @@ class ArabicCalendar extends Calendar implements CalendarInterface { * @param int $year * @return bool */ - public function leapYear($year) { + public function isLeapYear($year) { return ((11 * $year + 14) % 30) < 11; } /** * Convert a Julian day number into a year/month/day. * - * @param $jd + * @param int $julian_day * * @return int[]; */ - public function jdToYmd($jd) { - $year = (int)((30 * ($jd - 1948439) + 10646) / 10631); - $month = (int)((11 * ($jd - $year * 354 - (int)((3 + 11 * $year) / 30) - 1948085) + 330) / 325); - $day = $jd - 29 * ($month - 1) - (int)((6 * $month - 1) / 11) - $year * 354 - (int)((3 + 11 * $year) / 30) - 1948084; + public function jdToYmd($julian_day) { + $year = (int)((30 * ($julian_day - 1948439) + 10646) / 10631); + $month = (int)((11 * ($julian_day - $year * 354 - (int)((3 + 11 * $year) / 30) - 1948085) + 330) / 325); + $day = $julian_day - 29 * ($month - 1) - (int)((6 * $month - 1) / 11) - $year * 354 - (int)((3 + 11 * $year) / 30) - 1948084; return array($year, $month, $day); } @@ -85,32 +73,4 @@ class ArabicCalendar extends Calendar implements CalendarInterface { public function ymdToJd($year, $month, $day) { return $day + 29 * ($month - 1) + (int)((6 * $month - 1) / 11) + $year * 354 + (int)((3 + 11 * $year) / 30) + 1948084; } - - /** - * Month names for the calendar. - * - * @return string[] - */ - public function monthNames() { - return array( - 1 => 'Muharram', 'Safar', 'Rabi‘ I', 'Rabi‘ II', 'Jumada I', 'Jumada II', - 'Rajab', 'Sha‘aban', 'Ramadan', 'Shawwal', 'Dhu al-Qi‘dah', 'Dhu al-Hijjah', - ); - } - - /** - * 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 > self::MAX_MONTHS_IN_YEAR) { - return trigger_error('invalid date.', E_USER_WARNING); - } else { - return static::$DAYS_IN_MONTH[$this->leapYear($year)][$month]; - } - } } diff --git a/library/fisharebest/ext-calendar/src/Calendar.php b/library/fisharebest/ext-calendar/src/Calendar.php deleted file mode 100644 index 6884ac4aa6..0000000000 --- a/library/fisharebest/ext-calendar/src/Calendar.php +++ /dev/null @@ -1,200 +0,0 @@ -<?php -namespace Fisharebest\ExtCalendar; - -/** - * 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; - - /** - * 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', - ); - } - - /** - * 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(); - } -} diff --git a/library/fisharebest/ext-calendar/src/CalendarInterface.php b/library/fisharebest/ext-calendar/src/CalendarInterface.php index ca03634190..d3784a4a36 100644 --- a/library/fisharebest/ext-calendar/src/CalendarInterface.php +++ b/library/fisharebest/ext-calendar/src/CalendarInterface.php @@ -2,9 +2,11 @@ namespace Fisharebest\ExtCalendar; /** - * interface CalendarInterface - each calendar implementation needs to provide + * Interface CalendarInterface - each calendar implementation needs to provide * these methods. * + * Many of them are actually provided by the AbstractCalendar base class. + * * @author Greg Roach <fisharebest@gmail.com> * @copyright (c) 2014 Greg Roach * @license This program is free software: you can redistribute it and/or modify @@ -22,24 +24,23 @@ namespace Fisharebest\ExtCalendar; */ interface CalendarInterface { /** - * Convert a Julian day number into a year/month/day. + * Determine the number of days in a specified month, allowing for leap years, etc. * - * @param $jd + * @param int $year + * @param int $month * - * @return int[] + * @return int */ - public function jdToYmd($jd); + public function daysInMonth($year, $month); /** - * Convert a year/month/day to a Julian day number. + * Convert a Julian day number into a year/month/day. * - * @param int $year - * @param int $month - * @param int $day + * @param int $julian_day * - * @return int + * @return int[] */ - public function ymdToJd($year, $month, $day); + public function jdToYmd($julian_day); /** * Determine whether or not a given year is a leap-year. @@ -48,23 +49,16 @@ interface CalendarInterface { * * @return bool */ - public function leapYear($year); + public function isLeapYear($year); /** - * Determine the number of days in a specified month, allowing for leap years, etc. + * Convert a year/month/day to a Julian day number. * * @param int $year * @param int $month + * @param int $day * * @return int */ - public function daysInMonth($year, $month); - - /** - * Provide a list of month names, as required by PHP::cal_info() - * - * @return string[] - */ - public function monthNames(); - + public function ymdToJd($year, $month, $day); } diff --git a/library/fisharebest/ext-calendar/src/FrenchCalendar.php b/library/fisharebest/ext-calendar/src/FrenchCalendar.php index 18ead98495..dc74af24f6 100644 --- a/library/fisharebest/ext-calendar/src/FrenchCalendar.php +++ b/library/fisharebest/ext-calendar/src/FrenchCalendar.php @@ -2,7 +2,7 @@ namespace Fisharebest\ExtCalendar; /** - * class FrenchCalendar - calculations for the French Republican calendar. + * Class FrenchCalendar - calculations for the French Republican calendar. * * @author Greg Roach <fisharebest@gmail.com> * @copyright (c) 2014 Greg Roach @@ -19,16 +19,7 @@ namespace Fisharebest\ExtCalendar; * 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 FrenchCalendar extends Calendar implements CalendarInterface { - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_NAME = 'French'; - - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_NUMBER = 3; - - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_SYMBOL = 'CAL_FRENCH'; - +class FrenchCalendar extends AbstractCalendar implements CalendarInterface { /** See the GEDCOM specification */ const GEDCOM_CALENDAR_ESCAPE = '@#DFRENCH R@'; @@ -41,8 +32,15 @@ class FrenchCalendar extends Calendar implements CalendarInterface { /** The maximum number of months in any year */ const MAX_MONTHS_IN_YEAR = 13; - /** The maximum number of days in any month */ - const MAX_DAYS_IN_MONTH = 30; + /** + * Month lengths for regular years and leap-years. + * + * @var int[][] + */ + protected static $DAYS_IN_MONTH = array( + 0 => array(1 => 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 5), + 1 => array(1 => 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 6), + ); /** * Determine whether a year is a leap year. @@ -54,21 +52,21 @@ class FrenchCalendar extends Calendar implements CalendarInterface { * @param int $year * @return bool */ - public function leapYear($year) { + public function isLeapYear($year) { return $year % 4 == 3; } /** * Convert a Julian day number into a year/month/day. * - * @param $jd + * @param $julian_day * * @return int[]; */ - public function jdToYmd($jd) { - $year = (int)(($jd - 2375109) * 4 / 1461) - 1; - $month = (int)(($jd - 2375475 - $year * 365 - (int)($year / 4)) / 30) + 1; - $day = $jd - 2375444 - $month * 30 - $year * 365 - (int)($year / 4); + public function jdToYmd($julian_day) { + $year = (int)(($julian_day - 2375109) * 4 / 1461) - 1; + $month = (int)(($julian_day - 2375475 - $year * 365 - (int)($year / 4)) / 30) + 1; + $day = $julian_day - 2375444 - $month * 30 - $year * 365 - (int)($year / 4); return array($year, $month, $day); } @@ -85,40 +83,4 @@ class FrenchCalendar extends Calendar implements CalendarInterface { public function ymdToJd($year, $month, $day) { return 2375444 + $day + $month * 30 + $year * 365 + (int)($year / 4); } - - /** - * Month names for the calendar. - * - * @return string[] - */ - public function monthNames() { - return array( - 1 => 'Vendemiaire', 'Brumaire', 'Frimaire', 'Nivose', 'Pluviose', 'Ventose', - 'Germinal', 'Floreal', 'Prairial', 'Messidor', 'Thermidor', 'Fructidor', 'Extra', - ); - } - - /** - * Calculate the number of days in a month. - * - * @param int $year - * @param int $month - * - * @return int - */ - public function daysInMonth($year, $month) { - if ($year < 1 || $year > 14) { - return trigger_error('invalid date.', E_USER_WARNING); - } elseif ($month >=1 && $month <= 12) { - return 30; - } elseif ($month == 13) { - if ($this->leapYear($year)) { - return 6; - } else { - return $year == 14 ? -2380948 : 5; // Emulate a bug in PHP - } - } else { - return trigger_error('invalid date.', E_USER_WARNING); - } - } } diff --git a/library/fisharebest/ext-calendar/src/GregorianCalendar.php b/library/fisharebest/ext-calendar/src/GregorianCalendar.php index 2856a4210a..ae2d56442d 100644 --- a/library/fisharebest/ext-calendar/src/GregorianCalendar.php +++ b/library/fisharebest/ext-calendar/src/GregorianCalendar.php @@ -38,7 +38,7 @@ class GregorianCalendar extends JulianCalendar implements CalendarInterface { * @param int $year * @return bool */ - public function leapYear($year) { + public function isLeapYear($year) { if ($year < 0) { $year++; } @@ -49,21 +49,22 @@ class GregorianCalendar extends JulianCalendar implements CalendarInterface { /** * Convert a Julian day number into a year/month/day. * - * @param $jd + * @param $julian_day * * @return int[]; */ - public function jdToYmd($jd) { - $a = $jd + 32044; + public function jdToYmd($julian_day) { + $a = $julian_day + 32044; $b = (int)((4 * $a + 3) / 146097); $c = $a - (int)($b * 146097 / 4); $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; + + $day = $e - (int)((153 * $m + 2) / 5) + 1; $month = $m + 3 - 12 * (int)($m / 10); - $year = $b * 100 + $d - 4800 + (int)($m / 10); - if ($year < 1) { // 0=1BC, -1=2BC, etc. + $year = $b * 100 + $d - 4800 + (int)($m / 10); + if ($year < 1) { // 0 is 1 BCE, -1 is 2 BCE, etc. $year--; } @@ -84,8 +85,8 @@ class GregorianCalendar extends JulianCalendar implements CalendarInterface { // 1 B.C.E. => 0, 2 B.C.E> => 1, etc. ++$year; } - $a = (int)((14 - $month) / 12); - $year = $year + 4800 - $a; + $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) - (int)($year / 100) + (int)($year / 400) - 32045; @@ -114,7 +115,7 @@ class GregorianCalendar extends JulianCalendar implements CalendarInterface { $solar = (int)(($year - 1600) / 100) - (int)(($year - 1600) / 400); // The lunar correction - $lunar = (int)((int)(($year-1400) / 100) * 8) / 25; + $lunar = (int)((int)(($year - 1400) / 100) * 8) / 25; // The uncorrected “Paschal full moon” date $pfm = (3 - 11 * $golden + $solar - $lunar) % 30; @@ -123,7 +124,7 @@ class GregorianCalendar extends JulianCalendar implements CalendarInterface { } // The corrected “Paschal full moon” date - if ($pfm == 29 || $pfm == 28 && $golden > 11) { + if ($pfm === 29 || $pfm === 28 && $golden > 11) { $pfm--; } diff --git a/library/fisharebest/ext-calendar/src/JewishCalendar.php b/library/fisharebest/ext-calendar/src/JewishCalendar.php index adf8b2dc34..88d93896a3 100644 --- a/library/fisharebest/ext-calendar/src/JewishCalendar.php +++ b/library/fisharebest/ext-calendar/src/JewishCalendar.php @@ -1,10 +1,13 @@ <?php namespace Fisharebest\ExtCalendar; +use InvalidArgumentException; + /** - * class JewishCalendar - calculations for the Jewish calendar. + * Class JewishCalendar - calculations for the Jewish calendar. * - * Hebrew characters in this file have UTF-8 encoding. + * Hebrew characters in the code have ISO-8859-8 encoding (and ASCII punctuation). + * Hebrew characters in the comments have UTF-8 encoding (and Hebrew punctuation). * * @author Greg Roach <fisharebest@gmail.com> * @copyright (c) 2014 Greg Roach @@ -21,16 +24,7 @@ namespace Fisharebest\ExtCalendar; * 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 JewishCalendar extends Calendar implements CalendarInterface { - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_NAME = 'Jewish'; - - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_NUMBER = 2; - - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_SYMBOL = 'CAL_JEWISH'; - +class JewishCalendar extends AbstractCalendar implements CalendarInterface { /** See the GEDCOM specification */ const GEDCOM_CALENDAR_ESCAPE = '@#DHEBREW@'; @@ -40,20 +34,17 @@ class JewishCalendar extends Calendar implements CalendarInterface { /** The latest Julian Day number that can be converted into this calendar. */ const JD_END = 324542846; - /** The maximum number of days in any month. */ - const MAX_DAYS_IN_MONTH = 30; - /** The maximum number of months in any year. */ const MAX_MONTHS_IN_YEAR = 13; /** Place this symbol before the final letter of a sequence of numerals. */ - const GERSHAYIM = '״'; + const GERSHAYIM = '"'; // The gershayim symbol - ״ /** Place this symbol after a single numeral. */ - const GERESH = '׳'; + const GERESH = "'"; // The geresh symbol - ׳ /** Word for thousand. */ - const ALAFIM = 'אלפים'; + const ALAFIM = " \xe0\xec\xf4\xe9\xed "; // The hebrew word for thousand with leading/trailing spaces - אלפים /** A year that is one day shorter than normal. */ const DEFECTIVE_YEAR = -1; @@ -70,33 +61,33 @@ class JewishCalendar extends Calendar implements CalendarInterface { * @var string[] */ private static $HEBREW_NUMERALS = array( - 400 => 'ת', - 300 => 'ש', - 200 => 'ר', - 100 => 'ק', - 90 => 'צ', - 80 => 'פ', - 70 => 'ע', - 60 => 'ס', - 50 => 'נ', - 40 => 'מ', - 30 => 'ל', - 20 => 'כ', - 19 => 'יט', - 18 => 'יח', - 17 => 'יז', - 16 => 'טז', - 15 => 'טו', - 10 => 'י', - 9 => 'ט', - 8 => 'ח', - 7 => 'ז', - 6 => 'ו', - 5 => 'ה', - 4 => 'ד', - 3 => 'ג', - 2 => 'ב', - 1 => 'א', + 400 => "\xfa", // Tav - ת + 300 => "\xf9", // Shin - ש + 200 => "\xf8", // Resh - ר + 100 => "\xf7", // Kuf - ק + 90 => "\xf6", // Tsadi - צ + 80 => "\xf4", // Pei - פ + 70 => "\xf2", // Ayin - ע + 60 => "\xf1", // Samech - ס + 50 => "\xf0", // Nun - נ - (note that we don’t distinguish end nuns from regular nuns) + 40 => "\xee", // Mem - מ + 30 => "\xec", // Lamed - ל + 20 => "\xeb", // Kaf - כ + 19 => "\xe9\xe8", // Yud Tet - יט - (to prevent 19 matching 17 + 2) + 18 => "\xe9\xe7", // Yud Het - יח - (to prevent 18 matching 17 + 1) + 17 => "\xe9\xe6", // Yud Zayin - יז - (to prevent 17 matching 16 + 1) + 16 => "\xe8\xe6", // Tet Zayin - טז + 15 => "\xe8\xe5", // Tet Vav - טו + 10 => "\xe9", // Yud - י + 9 => "\xe8", // Tet - ט + 8 => "\xe7", // Het - ח + 7 => "\xe6", // Zayin -ז + 6 => "\xe5", // Vav - ו + 5 => "\xe4", // Hei - ה + 4 => "\xe3", // Dalet - ד + 3 => "\xe2", // Gimel - ג + 2 => "\xe1", // Bet - ב + 1 => "\xe0", // Aleph - א ); /** @@ -156,23 +147,23 @@ class JewishCalendar extends Calendar implements CalendarInterface { * * @return bool */ - public function leapYear($year) { + public function isLeapYear($year) { return (7 * $year + 1) % 19 < 7; } /** * Convert a Julian day number into a year. * - * @param int $jd + * @param int $julian_day * * @return int; */ - protected function jdToY($jd) { + protected function jdToY($julian_day) { // Generate an approximate year - may be out by one either way. Add one to it. - $year = (int)(($jd - 347998) / 365) + 1; + $year = (int)(($julian_day - 347998) / 365) + 1; // Adjust by subtracting years; - while ($this->yToJd($year) > $jd) { + while ($this->yToJd($year) > $julian_day) { $year--; } @@ -182,25 +173,23 @@ class JewishCalendar extends Calendar implements CalendarInterface { /** * Convert a Julian day number into a year/month/day. * - * @param int $jd + * @param int $julian_day * * @return int[]; */ - public function jdToYmd($jd) { - // Find the year - $year = $this->jdToY($jd); - - // Add one month at a time, to use up the remaining days. + public function jdToYmd($julian_day) { + // Find the year, by adding one month at a time to use up the remaining days. + $year = $this->jdToY($julian_day); $month = 1; - $day = $jd - $this->yToJd($year) + 1; + $day = $julian_day - $this->yToJd($year) + 1; while ($day > $this->daysInMonth($year, $month)) { $day -= $this->daysInMonth($year, $month); - $month += 1; + $month++; } // PHP 5.4 and earlier converted non leap-year Adar into month 6, instead of month 7. - $month -= (Shim::emulateBug54254() && $month == 7 && !$this->leapYear($year)) ? 1 : 0; + $month -= (Shim::shouldEmulateBug54254() && $month === 7 && !$this->isLeapYear($year)) ? 1 : 0; return array($year, $month, $day); } @@ -215,22 +204,23 @@ class JewishCalendar extends Calendar implements CalendarInterface { protected function yToJd($year) { $div19 = (int)(($year - 1) / 19); $mod19 = ($year - 1) % 19; - $months = 235 * $div19 + 12 * $mod19 + (int)((7 * $mod19 + 1) / 19); - $parts = 204 + 793 * ($months % 1080); - $hours = 5 + 12 * $months + 793 * (int)($months / 1080) + (int)($parts / 1080); + + $months = 235 * $div19 + 12 * $mod19 + (int)((7 * $mod19 + 1) / 19); + $parts = 204 + 793 * ($months % 1080); + $hours = 5 + 12 * $months + 793 * (int)($months / 1080) + (int)($parts / 1080); $conjunction = 1080 * ($hours % 24) + ($parts % 1080); - $jd = 1 + 29 * $months + (int)($hours / 24); + $julian_day = 1 + 29 * $months + (int)($hours / 24); if ( $conjunction >= 19440 || - $jd % 7 === 2 && $conjunction >= 9924 && !$this->leapYear($year) || - $jd % 7 === 1 && $conjunction >= 16789 && $this->leapYear($year - 1) + $julian_day % 7 === 2 && $conjunction >= 9924 && !$this->isLeapYear($year) || + $julian_day % 7 === 1 && $conjunction >= 16789 && $this->isLeapYear($year - 1) ) { - $jd++; + $julian_day++; } // The actual year start depends on the day of the week - return $jd + self::$ROSH_HASHANAH[$jd % 7]; + return $julian_day + self::$ROSH_HASHANAH[$julian_day % 7]; } /** @@ -245,14 +235,14 @@ class JewishCalendar extends Calendar implements CalendarInterface { public function ymdToJd($year, $month, $day) { return $this->yToJd($year) + - self::$CUMULATIVE_DAYS[$this->leapYear($year)][$this->yearType($year)][$month] + + self::$CUMULATIVE_DAYS[$this->isLeapYear($year)][$this->yearType($year)][$month] + $day - 1; } /** * Determine whether a year is normal, defective or complete. * - * @param $year + * @param int $year * * @return int defective (-1), normal (0) or complete (1) */ @@ -306,7 +296,7 @@ class JewishCalendar extends Calendar implements CalendarInterface { * @return int */ private function daysInMonthAdarI($year) { - if ($this->leapYear($year)) { + if ($this->isLeapYear($year)) { return 30; } else { return 0; @@ -320,15 +310,19 @@ class JewishCalendar extends Calendar implements CalendarInterface { * @param int $month * * @return int + * + * @throws InvalidArgumentException */ public function daysInMonth($year, $month) { - if ($year === 0 || $month < 1 || $month > 13) { - return trigger_error('invalid date.', E_USER_WARNING); - } elseif ($month === 2) { + if ($year < 1) { + throw new InvalidArgumentException('Year ' . $year . ' is invalid for this calendar'); + } elseif ($month < 1 || $month > self::MAX_MONTHS_IN_YEAR) { + throw new InvalidArgumentException('Month ' . $month . ' is invalid for this calendar'); + } elseif ($month == 2) { return $this->daysInMonthHeshvan($year); - } elseif ($month === 3) { + } elseif ($month == 3) { return $this->daysInMonthKislev($year); - } elseif ($month === 6) { + } elseif ($month == 6) { return $this->daysInMonthAdarI($year); } else { return self::$FIXED_MONTH_LENGTHS[$month]; @@ -336,52 +330,6 @@ class JewishCalendar extends Calendar implements CalendarInterface { } /** - * Month names. - * - * @link https://bugs.php.net/bug.php?id=54254 - * - * @return string[] - */ - public function monthNames() { - return array( - 1 => 'Tishri', 'Heshvan', 'Kislev', 'Tevet', 'Shevat', - Shim::emulateBug54254() ? 'AdarI' : 'Adar I', - Shim::emulateBug54254() ? 'AdarII' : 'Adar II', - 'Nisan', 'Iyyar', 'Sivan', 'Tammuz', 'Av', 'Elul', - ); - } - - /** - * Calculate the name of a month, for a specified Julian Day number. - * - * @param $jd - * - * @return string - */ - public function jdMonthName($jd) { - list($year, $month) = $this->jdToYmd($jd); - $months = $this->monthNames(); - - if (!$this->leapYear($year) && ($month === 6 || $month === 7)) { - return Shim::emulateBug54254() ? 'AdarI' : 'Adar'; - } else { - return $months[$month]; - } - } - - /** - * Calculate the name of a month, for a specified Julian Day number. - * - * @param int $jd - * - * @return string - */ - public function jdMonthNameAbbreviated($jd) { - return $this->jdMonthName($jd); - } - - - /** * Hebrew month names. * * @link https://bugs.php.net/bug.php?id=54254 @@ -391,13 +339,22 @@ class JewishCalendar extends Calendar implements CalendarInterface { * @return string[] */ protected function hebrewMonthNames($year) { - $leap_year = $this->leapYear($year); + $leap_year = $this->isLeapYear($year); return array( - 1 => 'תשרי', 'חשון', 'כסלו', 'טבת', 'שבט', - $leap_year ? (Shim::emulateBug54254() ? 'אדר' : 'אדר א׳') : 'אדר', - $leap_year ? (Shim::emulateBug54254() ? '\'אדר ב' : 'אדר ב׳') : 'אדר', - 'ניסן', 'אייר', 'סיון', 'תמוז', 'אב', 'אלול', + 1 => "\xfa\xf9\xf8\xe9", // Tishri - תשרי + "\xe7\xf9\xe5\xef", // Heshvan - חשון + "\xeb\xf1\xec\xe5", // Kislev - כסלו + "\xe8\xe1\xfa", // Tevet - טבת + "\xf9\xe1\xe8", // Shevat - שבט + $leap_year ? (Shim::shouldEmulateBug54254() ? "\xe0\xe3\xf8" : "\xe0\xe3\xf8 \xe0'") : "\xe0\xe3\xf8", // Adar I - אדר - אדר א׳ - אדר + $leap_year ? (Shim::shouldEmulateBug54254() ? "'\xe0\xe3\xf8 \xe1" : "\xe0\xe3\xf8 \xe1'") : "\xe0\xe3\xf8", // Adar II - 'אדר ב - אדר ב׳ - אדר + "\xf0\xe9\xf1\xef", // Nisan - ניסן + "\xe0\xe9\xe9\xf8", // Iyar - אייר + "\xf1\xe9\xe5\xef", // Sivan - סיון + "\xfa\xee\xe5\xe6", // Tammuz - תמוז + "\xe0\xe1", // Av - אב + "\xe0\xec\xe5\xec", // Elul - אלול ); } @@ -420,12 +377,12 @@ class JewishCalendar extends Calendar implements CalendarInterface { * * Gereshayim is a contraction of “geresh” and “gershayim”. * - * @param string $number + * @param string $hebrew * * @return string */ protected function addGereshayim($hebrew) { - switch (mb_strlen($hebrew, 'UTF-8')) { + switch (strlen($hebrew)) { case 0: // Zero, e.g. the zeros from the year 5,000 return $hebrew; @@ -434,7 +391,7 @@ class JewishCalendar extends Calendar implements CalendarInterface { return $hebrew . self::GERESH; default: // Multiple digits - insert a gershayim - return mb_substr($hebrew, 0, mb_strlen($hebrew, 'UTF-8') - 1, 'UTF-8') . self::GERSHAYIM . mb_substr($hebrew, -1, 1, 'UTF-8'); + return substr($hebrew, 0, strlen($hebrew) - 1) . self::GERSHAYIM . substr($hebrew, -1, 1); } } @@ -485,7 +442,7 @@ class JewishCalendar extends Calendar implements CalendarInterface { $thousands .= self::GERESH; } if ($alafim) { - $thousands .= ' ' . self::ALAFIM . ' '; + $thousands .= self::ALAFIM; } return $thousands . $this->numberToHebrewNumerals($year % 1000, $gereshayim); } @@ -494,15 +451,15 @@ class JewishCalendar extends Calendar implements CalendarInterface { /** * Convert a Julian Day number into a Hebrew date. * - * @param int $jd + * @param int $julian_day * @param bool $alafim_garesh * @param bool $alafim * @param bool $gereshayim * * @return string $string */ - public function jdToHebrew($jd, $alafim_garesh, $alafim, $gereshayim) { - list($year, $month, $day) = $this->jdToYmd($jd); + public function jdToHebrew($julian_day, $alafim_garesh, $alafim, $gereshayim) { + list($year, $month, $day) = $this->jdToYmd($julian_day); return $this->numberToHebrewNumerals($day, $gereshayim) . ' ' . diff --git a/library/fisharebest/ext-calendar/src/JulianCalendar.php b/library/fisharebest/ext-calendar/src/JulianCalendar.php index c74e82cda2..05b38a6552 100644 --- a/library/fisharebest/ext-calendar/src/JulianCalendar.php +++ b/library/fisharebest/ext-calendar/src/JulianCalendar.php @@ -2,7 +2,7 @@ namespace Fisharebest\ExtCalendar; /** - * class JulianCalendar - calculations for the Julian calendar. + * Class JulianCalendar - calculations for the Julian calendar. * * @author Greg Roach <fisharebest@gmail.com> * @copyright (c) 2014 Greg Roach @@ -19,19 +19,13 @@ namespace Fisharebest\ExtCalendar; * 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'; - +class JulianCalendar extends AbstractCalendar implements CalendarInterface { /** See the GEDCOM specification */ const GEDCOM_CALENDAR_ESCAPE = '@#DJULIAN@'; + /** Does the calendar start at year 1, or are we allowed negative (BCE) years. */ + const NEGATIVE_YEARS_ALLOWED = true; + /** * Month lengths for regular years and leap-years. * @@ -43,35 +37,12 @@ class JulianCalendar extends Calendar implements CalendarInterface { ); /** - * 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) { + public function isLeapYear($year) { if ($year < 0) { $year++; } @@ -82,20 +53,21 @@ class JulianCalendar extends Calendar implements CalendarInterface { /** * Convert a Julian day number into a year/month/day. * - * @param $jd + * @param $julian_day * * @return int[]; */ - public function jdToYmd($jd) { - $c = $jd + 32082; + public function jdToYmd($julian_day) { + $c = $julian_day + 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; + + $day = $e - (int)((153 * $m + 2) / 5) + 1; $month = $m + 3 - 12 * (int)($m / 10); - $year = $d - 4800 + (int)($m / 10); + $year = $d - 4800 + (int)($m / 10); if ($year < 1) { - // 0=1BC, -1=2BC, etc. + // 0 is 1 BCE, -1 is 2 BCE, etc. $year--; } @@ -113,33 +85,17 @@ class JulianCalendar extends Calendar implements CalendarInterface { */ public function ymdToJd($year, $month, $day) { if ($year < 0) { - // 1 B.C.E. => 0, 2 B.C.E> => 1, etc. + // 1 BCE is 0, 2 BCE is -1, etc. ++$year; } - $a = (int)((14 - $month) / 12); - $year = $year + 4800 - $a; + $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 @@ -165,7 +121,7 @@ class JulianCalendar extends Calendar implements CalendarInterface { } // The corrected “Paschal full moon” date - if ($pfm == 29 || $pfm == 28 && $golden > 11) { + if ($pfm === 29 || $pfm === 28 && $golden > 11) { $pfm--; } diff --git a/library/fisharebest/ext-calendar/src/PersianCalendar.php b/library/fisharebest/ext-calendar/src/PersianCalendar.php index 85f0f44af0..179c93b074 100644 --- a/library/fisharebest/ext-calendar/src/PersianCalendar.php +++ b/library/fisharebest/ext-calendar/src/PersianCalendar.php @@ -2,7 +2,7 @@ namespace Fisharebest\ExtCalendar; /** - * class PersianCalendar - calculations for the Persian (Jalali) calendar. + * Class PersianCalendar - calculations for the Persian (Jalali) calendar. * * @author Greg Roach <fisharebest@gmail.com> * @copyright (c) 2014 Greg Roach @@ -19,21 +19,12 @@ namespace Fisharebest\ExtCalendar; * 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 PersianCalendar extends Calendar implements CalendarInterface { - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_NAME = 'Persian'; - - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_NUMBER = 5; // PHP uses 0-3 - - /** Same as PHP’s ext/calendar extension */ - const PHP_CALENDAR_SYMBOL = 'CAL_PERSIAN'; - +class PersianCalendar extends AbstractCalendar implements CalendarInterface { /** See the GEDCOM specification */ const GEDCOM_CALENDAR_ESCAPE = '@#DJALALI@'; /** The earliest Julian Day number that can be converted into this calendar. */ - const JD_START = 1948321; // 1 Farvardīn 0001 AP = ?? ??? ???? (Julian) + const JD_START = 1948320; // 1 Farvardīn 0001 AP = 19 MAR 0622 (Julian) /** * Month lengths for regular years and leap-years. @@ -60,36 +51,34 @@ class PersianCalendar extends Calendar implements CalendarInterface { * @param int $year * @return bool */ - public function leapYear($year) { + public function isLeapYear($year) { return in_array((($year + 2346) % 2820) % 128, self::$LEAP_YEAR_CYCLE); } /** * Convert a Julian day number into a year/month/day. * - * @param $jd + * @param $julian_day * * @return int[]; */ - public function jdToYmd($jd) { - $depoch = $jd - $this->ymdToJd(475, 1, 1); - $cycle = (int)($depoch / 1029983); - $cyear = $depoch % 1029983; + public function jdToYmd($julian_day) { + $depoch = $julian_day - 2121447; + $cycle = (int)($depoch / 1029983); + $cyear = $depoch % 1029983; if ($cyear == 1029982) { $ycycle = 2820; } else { - $aux1 = (int)($cyear / 366); - $aux2 = $cyear % 366; - $ycycle = (int)(((2134 * $aux1) + (2816 * $aux2) + 2815) / 1028522) + - $aux1 + 1; + $aux1 = (int)($cyear / 366); + $aux2 = $cyear % 366; + $ycycle = (int)(((2134 * $aux1) + (2816 * $aux2) + 2815) / 1028522) + $aux1 + 1; } $year = $ycycle + (2820 * $cycle) + 474; - if ($year <= 0) { - $year--; - } - $yday = ($jd - $this->ymdToJd($year, 1, 1)) + 1; + + // If we allowed negative years, we would deal with them here. + $yday = ($julian_day - $this->ymdToJd($year, 1, 1)) + 1; $month = ($yday <= 186) ? ceil($yday / 31) : ceil(($yday - 6) / 30); - $day = ($jd - $this->ymdToJd($year, $month, 1)) + 1; + $day = ($julian_day - $this->ymdToJd($year, $month, 1)) + 1; return array($year, (int)$month, (int)$day); } @@ -113,34 +102,6 @@ class PersianCalendar extends Calendar implements CalendarInterface { (int)((($epyear * 682) - 110) / 2816) + ($epyear - 1) * 365 + (int)($epbase / 2820) * 1029983 + - (self::JD_START - 1); - } - - /** - * Month names for the calendar. - * - * @return string[] - */ - public function monthNames() { - return array( - 1 => 'Farvardin', 'Ordibehesht', 'Khordad', 'Tir', 'Mordad', 'Shahrivar', - 'Mehr', 'Aban', 'Azar', 'Dey', 'Bahman', 'Esfand', - ); - } - - /** - * 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 > self::MAX_MONTHS_IN_YEAR) { - return trigger_error('invalid date.', E_USER_WARNING); - } else { - return static::$DAYS_IN_MONTH[$this->leapYear($year)][$month]; - } + self::JD_START; } } diff --git a/library/fisharebest/ext-calendar/src/Shim.php b/library/fisharebest/ext-calendar/src/Shim.php index fc6e468b15..4a87a326b5 100644 --- a/library/fisharebest/ext-calendar/src/Shim.php +++ b/library/fisharebest/ext-calendar/src/Shim.php @@ -1,6 +1,8 @@ <?php namespace Fisharebest\ExtCalendar; +use InvalidArgumentException; + /** * class Shim - PHP implementations of functions from the PHP calendar extension. * @@ -22,15 +24,93 @@ namespace Fisharebest\ExtCalendar; * along with this program. If not, see <http://www.gnu.org/licenses/>. */ class Shim { + /** @var FrenchCalendar */ + private static $french_calendar; + + /** @var GregorianCalendar */ + private static $gregorian_calendar; + + /** @var JewishCalendar */ + private static $jewish_calendar; + + /** @var JulianCalendar */ + private static $julian_calendar; + + /** + * English names for the days of the week. + * + * @var string[] + */ + private static $DAY_NAMES = array( + 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', + ); + + /** + * Abbreviated English names for the days of the week. + * + * @var string[] + */ + private static $DAY_NAMES_SHORT = array( + 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', + ); + + /** @var string[] Names of the months of the Gregorian/Julian calendars */ + private static $MONTH_NAMES = array( + '', 'January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December', + ); + + /** @var string[] Abbreviated names of the months of the Gregorian/Julian calendars */ + private static $MONTH_NAMES_SHORT = array( + '', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', + ); + + /** @var string[] Name of the months of the French calendar */ + private static $MONTH_NAMES_FRENCH = array( + '', 'Vendemiaire', 'Brumaire', 'Frimaire', 'Nivose', 'Pluviose', 'Ventose', + 'Germinal', 'Floreal', 'Prairial', 'Messidor', 'Thermidor', 'Fructidor', 'Extra' + ); + + /** @var string[] Names of the months of the Jewish calendar in a non-leap year */ + private static $MONTH_NAMES_JEWISH = array( + '', 'Tishri', 'Heshvan', 'Kislev', 'Tevet', 'Shevat', 'Adar', + 'Adar', 'Nisan', 'Iyyar', 'Sivan', 'Tammuz', 'Av', 'Elul', + ); + + /** @var string[] Names of the months of the Jewish calendar in a leap year */ + private static $MONTH_NAMES_JEWISH_LEAP_YEAR = array( + '', 'Tishri', 'Heshvan', 'Kislev', 'Tevet', 'Shevat', 'Adar I', + 'Adar II', 'Nisan', 'Iyyar', 'Sivan', 'Tammuz', 'Av', 'Elul', + ); + + /** @var string[] Names of the months of the Jewish calendar (before PHP bug 54254 was fixed)*/ + private static $MONTH_NAMES_JEWISH_54254 = array( + '', 'Tishri', 'Heshvan', 'Kislev', 'Tevet', 'Shevat', 'AdarI', + 'AdarII', 'Nisan', 'Iyyar', 'Sivan', 'Tammuz', 'Av', 'Elul', + ); + /** * Create the necessary shims to emulate the ext/calendar packate. * + * @param null|FrenchCalendar $french_calendar + * @param null|GregorianCalendar $gregorian_calendar + * @param null|JewishCalendar $jewish_calendar + * @param null|JulianCalendar $julian_calendar + * * @return void */ - public static function create() { - if (!function_exists('cal_info')) { - require __DIR__ . '/shims.php'; - } + public static function create( + FrenchCalendar $french_calendar = null, + GregorianCalendar $gregorian_calendar = null, + JewishCalendar $jewish_calendar = null, + JulianCalendar $julian_calendar = null + ) { + self::$french_calendar = $french_calendar ?: new FrenchCalendar; + self::$gregorian_calendar = $gregorian_calendar ?: new GregorianCalendar; + self::$jewish_calendar = $jewish_calendar ?: new JewishCalendar; + self::$julian_calendar = $julian_calendar ?: new JulianCalendar; + + defined('CAL_NUM_CALS') || require __DIR__ . '/shims.php'; } /** @@ -44,7 +124,7 @@ class Shim { * * @return bool */ - public static function emulateBug54254() { + public static function shouldEmulateBug54254() { return version_compare(PHP_VERSION, '5.5.0', '<'); } @@ -60,126 +140,216 @@ class Shim { * * @return bool */ - public static function emulateBug67960() { + public static function shouldEmulateBug67960() { + return true; + } + + /** + * Do we need to emulate PHP bug #67976? + * + * This bug relates to the number of days in the month 13 of year 14 in + * the French calendar. + * + * @link https://bugs.php.net/bug.php?id=67976 + * + * @return bool + */ + public static function shouldEmulateBug67976() { return true; } /** * Return the number of days in a month for a given year and calendar. * - * Shim implementation of \cal_days_in_month() + * Shim implementation of cal_days_in_month() * * @link https://php.net/cal_days_in_month + * @link https://bugs.php.net/bug.php?id=67976 * - * @param $calendar - * @param $month - * @param $year + * @param int $calendar_id + * @param int $month + * @param int $year * * @return int The number of days in the specified month */ - public static function calDaysInMonth($calendar, $month, $year) { - switch ($calendar) { - case CAL_GREGORIAN: - $gregorian = new GregorianCalendar; - return $gregorian->daysInMonth($year, $month); + public static function calDaysInMonth($calendar_id, $month, $year) { + switch ($calendar_id) { + case CAL_FRENCH: + return self::calDaysInMonthFrench($year, $month); - case CAL_JULIAN: - $julian= new JulianCalendar; - return $julian->daysInMonth($year, $month); + case CAL_GREGORIAN: + return self::calDaysInMonthCalendar(self::$gregorian_calendar, $year, $month); - case CAL_FRENCH: - $french = new FrenchCalendar(); - return $french->daysInMonth($year, $month); + case CAL_JEWISH: + return self::calDaysInMonthCalendar(self::$jewish_calendar, $year, $month); - case CAL_JEWISH: - $jewish = new JewishCalendar(); - return $jewish->daysInMonth($year, $month); + case CAL_JULIAN: + return self::calDaysInMonthCalendar(self::$julian_calendar, $year, $month); - default: - return trigger_error('invalid calendar ID ' . $calendar . '.', E_USER_WARNING); + default: + return trigger_error('invalid calendar ID ' . $calendar_id, E_USER_WARNING); + } + } + + /** + * Calculate the number of days in a month in a specified (Gregorian or Julian) calendar. + * + * @param CalendarInterface $calendar + * @param int $year + * @param int $month + * + * @return int + */ + private static function calDaysInMonthCalendar(CalendarInterface $calendar, $year, $month) { + try { + return $calendar->daysInMonth($year, $month); + } catch (InvalidArgumentException $ex){ + return trigger_error('invalid date.', E_USER_WARNING); + } + } + + /** + * Calculate the number of days in a month in the French calendar. + * + * Mimic PHP’s validation of the parameters + * + * @param int $year + * @param int $month + * + * @return int + */ + private static function calDaysInMonthFrench($year, $month) { + if ($month == 13 && $year == 14 && self::shouldEmulateBug67976()) { + return -2380948; + } elseif ($year > 14) { + return trigger_error('invalid date.', E_USER_WARNING); + } else { + return self::calDaysInMonthCalendar(self::$french_calendar, $year, $month); } } /** * Converts from Julian Day Count to a supported calendar. * - * Shim implementation of \cal_from_jd() + * Shim implementation of cal_from_jd() * * @link https://php.net/cal_from_jd * - * @param int $jd Julian Day number - * @param int $calendar Calendar constant + * @param int $julian_day Julian Day number + * @param int $calendar_id Calendar constant * * @return array */ - public static function calFromJd($jd, $calendar) { - switch ($calendar) { + public static function calFromJd($julian_day, $calendar_id) { + switch ($calendar_id) { case CAL_FRENCH: - $french = new FrenchCalendar; - return $french->calFromJd($jd); + return self::calFromJdCalendar($julian_day, self::jdToFrench($julian_day), self::$MONTH_NAMES_FRENCH, self::$MONTH_NAMES_FRENCH); case CAL_GREGORIAN: - $gregorian = new GregorianCalendar; - return $gregorian->calFromJd($jd); + return self::calFromJdCalendar($julian_day, self::jdToGregorian($julian_day), self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT); case CAL_JEWISH: - $jewish = new JewishCalendar; - return $jewish->calFromJd($jd); + $months = self::jdMonthNameJewishMonths($julian_day); + return self::calFromJdCalendar($julian_day, self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846), $months, $months); case CAL_JULIAN: - $julian = new JulianCalendar; - return $julian->calFromJd($jd); + return self::calFromJdCalendar($julian_day, self::jdToJulian($julian_day), self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT); default: - return trigger_error('invalid calendar ID ' . $calendar, E_USER_WARNING); + return trigger_error('invalid calendar ID ' . $calendar_id, E_USER_WARNING); } } /** + * Convert a Julian day number to a calendar and provide details. + * + * @param int $julian_day + * @param string $mdy + * @param string[] $months + * @param string[] $months_short + * + * @return mixed[] + */ + private static function calFromJdCalendar($julian_day, $mdy, $months, $months_short) { + list($month, $day, $year) = explode('/', $mdy); + + return array( + 'date' => $month . '/' . $day . '/' . $year, + 'month' => (int)$month, + 'day' => (int)$day, + 'year' => (int)$year, + 'dow' => self::jdDayOfWeek($julian_day, 0), + 'abbrevdayname' => self::jdDayOfWeek($julian_day, 2), + 'dayname' => self::jdDayOfWeek($julian_day, 1), + 'abbrevmonth' => $months_short[$month], + 'monthname' => $months[$month], + ); + } + + /** * Returns information about a particular calendar. * - * Shim implementation of \cal_info() + * Shim implementation of cal_info() * * @link https://php.net/cal_info * - * @param int $calendar + * @param int $calendar_id * - * @return array + * @return mixed[] */ - public static function calInfo($calendar) { - switch ($calendar) { - case -1: - return array( - CAL_GREGORIAN => static::calInfo(CAL_GREGORIAN), - CAL_JULIAN => static::calInfo(CAL_JULIAN), - CAL_JEWISH => static::calInfo(CAL_JEWISH), - CAL_FRENCH => static::calInfo(CAL_FRENCH), - ); - case CAL_FRENCH: - $french = new FrenchCalendar; - return $french->phpCalInfo(); + public static function calInfo($calendar_id) { + switch ($calendar_id) { + case CAL_FRENCH: + return self::calInfoCalendar(self::$MONTH_NAMES_FRENCH, self::$MONTH_NAMES_FRENCH, 30, 'French', 'CAL_FRENCH'); - case CAL_GREGORIAN: - $gregorian = new GregorianCalendar; - return $gregorian->phpCalInfo(); + case CAL_GREGORIAN: + return self::calInfoCalendar(self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT, 31, 'Gregorian', 'CAL_GREGORIAN'); - case CAL_JEWISH: - $jewish = new JewishCalendar; - return $jewish->phpCalInfo(); + case CAL_JEWISH: + $months = self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH_LEAP_YEAR; + return self::calInfoCalendar($months, $months, 30, 'Jewish', 'CAL_JEWISH'); - case CAL_JULIAN: - $julian = new JulianCalendar; - return $julian->phpCalInfo(); + case CAL_JULIAN: + return self::calInfoCalendar(self::$MONTH_NAMES, self::$MONTH_NAMES_SHORT, 31, 'Julian', 'CAL_JULIAN'); - default: - return trigger_error('invalid calendar ID ' . $calendar . '.', E_USER_WARNING); + case -1: + return array( + CAL_GREGORIAN => self::calInfo(CAL_GREGORIAN), + CAL_JULIAN => self::calInfo(CAL_JULIAN), + CAL_JEWISH => self::calInfo(CAL_JEWISH), + CAL_FRENCH => self::calInfo(CAL_FRENCH), + ); + + default: + return trigger_error('invalid calendar ID ' . $calendar_id, E_USER_WARNING); } } /** + * Returns information about the French calendar. + * + * @param string[] $month_names + * @param string[] $month_names_short + * @param int $max_days_in_month + * @param string $calendar_name + * @param string $calendar_symbol + * + * @return mixed[] + */ + private static function calInfoCalendar($month_names, $month_names_short, $max_days_in_month, $calendar_name, $calendar_symbol) { + return array( + 'months' => array_slice($month_names, 1, null, true), + 'abbrevmonths' => array_slice($month_names_short, 1, null, true), + 'maxdaysinmonth' => $max_days_in_month, + 'calname' => $calendar_name, + 'calsymbol' => $calendar_symbol, + ); + } + + /** * Converts from a supported calendar to Julian Day Count * - * Shim implementation of \cal_to_jd() + * Shim implementation of cal_to_jd() * * @link https://php.net/cal_to_jd * @@ -193,16 +363,16 @@ class Shim { public static function calToJd($calendar, $month, $day, $year) { switch ($calendar) { case CAL_FRENCH: - return Shim::frenchToJd($month, $day, $year); + return self::frenchToJd($month, $day, $year); case CAL_GREGORIAN: - return Shim::gregorianToJd($month, $day, $year); + return self::gregorianToJd($month, $day, $year); case CAL_JEWISH: - return Shim::jewishToJd($month, $day, $year); + return self::jewishToJd($month, $day, $year); case CAL_JULIAN: - return Shim::julianToJd($month, $day, $year); + return self::julianToJd($month, $day, $year); default: return trigger_error('invalid calendar ID ' . $calendar . '.', E_USER_WARNING); @@ -212,7 +382,7 @@ class Shim { /** * Get Unix timestamp for midnight on Easter of a given year. * - * Shim implementation of \easter_date() + * Shim implementation of easter_date() * * @link https://php.net/easter_date * @@ -225,24 +395,23 @@ class Shim { return trigger_error('This function is only valid for years between 1970 and 2037 inclusive', E_USER_WARNING); } - $gregorian = new GregorianCalendar; - $days = $gregorian->easterDays($year); + $days = self::$gregorian_calendar->easterDays($year); // Calculate time-zone offset - $date_time = new \DateTime('now', new \DateTimeZone(date_default_timezone_get())); + $date_time = new \DateTime('now', new \DateTimeZone(date_default_timezone_get())); $offset_seconds = $date_time->format('Z'); if ($days < 11) { - return jdtounix($gregorian->ymdToJd($year, 3, $days + 21)) - $offset_seconds; + return jdtounix(self::$gregorian_calendar->ymdToJd($year, 3, $days + 21)) - $offset_seconds; } else { - return jdtounix($gregorian->ymdToJd($year, 4, $days - 10)) - $offset_seconds; + return jdtounix(self::$gregorian_calendar->ymdToJd($year, 4, $days - 10)) - $offset_seconds; } } /** * Get number of days after March 21 on which Easter falls for a given year. * - * Shim implementation of \easter_days() + * Shim implementation of easter_days() * * @link https://php.net/easter_days * @@ -252,35 +421,21 @@ class Shim { * @return int */ public static function easterDays($year, $method) { - $julian = new JulianCalendar; - $gregorian = new GregorianCalendar; - - switch ($method) { - case CAL_EASTER_ROMAN: - if ($year <= 1582) { - return $julian->easterDays($year); - } else { - return $gregorian->easterDays($year); - } - case CAL_EASTER_ALWAYS_GREGORIAN: - return $gregorian->easterDays($year); - - case CAL_EASTER_ALWAYS_JULIAN: - return $julian->easterDays($year); - - default: // CAL_EASTER_DEFAULT or any other value - if ($year <= 1752) { - return $julian->easterDays($year); - } else { - return $gregorian->easterDays($year); - } + if ( + $method == CAL_EASTER_ALWAYS_JULIAN || + $method == CAL_EASTER_ROMAN && $year <= 1582 || + $year <= 1752 && $method != CAL_EASTER_ROMAN && $method != CAL_EASTER_ALWAYS_GREGORIAN + ) { + return self::$julian_calendar->easterDays($year); + } else { + return self::$gregorian_calendar->easterDays($year); } } /** * Converts a date from the French Republican Calendar to a Julian Day Count. * - * Shim implementation of \FrenchToJD() + * Shim implementation of FrenchToJD() * * @link https://php.net/FrenchToJD * @@ -291,19 +446,17 @@ class Shim { * @return int */ public static function frenchToJd($month, $day, $year) { - if ($year == 0) { + if ($year <= 0) { return 0; } else { - $french = new FrenchCalendar; - - return $french->ymdToJd($year, $month, $day); + return self::$french_calendar->ymdToJd($year, $month, $day); } } /** * Converts a Gregorian date to Julian Day Count. * - * Shim implementation of \GregorianToJD() + * Shim implementation of GregorianToJD() * * @link https://php.net/GregorianToJD * @@ -317,185 +470,224 @@ class Shim { if ($year == 0) { return 0; } else { - $gregorian = new GregorianCalendar; - - return $gregorian->ymdToJd($year, $month, $day); + return self::$gregorian_calendar->ymdToJd($year, $month, $day); } } /** * Returns the day of the week. * - * Shim implementation of \JDDayOfWeek() + * Shim implementation of JDDayOfWeek() * * @link https://php.net/JDDayOfWeek * @link https://bugs.php.net/bug.php?id=67960 * - * @param int $julianday + * @param int $julian_day * @param int $mode * - * @return mixed + * @return int|string */ - public static function jdDayOfWeek($julianday, $mode) { - $julian = new JulianCalendar; - $dow = $julian->dayOfWeek($julianday); + public static function jdDayOfWeek($julian_day, $mode) { + $day_of_week = ($julian_day + 1) % 7; + if ($day_of_week < 0) { + $day_of_week += 7; + } switch ($mode) { case 1: // 1, not CAL_DOW_LONG - see bug 67960 - return $julian->dayName($dow); + return self::$DAY_NAMES[$day_of_week]; + case 2: // 2, not CAL_DOW_SHORT - see bug 67960 - return $julian->dayNameAbbreviated($dow); + return self::$DAY_NAMES_SHORT[$day_of_week]; + default: // CAL_DOW_DAYNO or anything else - return $dow; + return $day_of_week; } } /** * Returns a month name. * - * Shim implementation of \JDMonthName() + * Shim implementation of JDMonthName() * * @link https://php.net/JDMonthName * - * @param int $julianday + * @param int $julian_day * @param int $mode * - * @return mixed + * @return string */ - public static function jdMonthName($julianday, $mode) { + public static function jdMonthName($julian_day, $mode) { switch ($mode) { case CAL_MONTH_GREGORIAN_LONG: - $gregorian = new GregorianCalendar; - return $gregorian->jdMonthName($julianday); + return self::jdMonthNameCalendar(self::$gregorian_calendar, $julian_day, self::$MONTH_NAMES); case CAL_MONTH_JULIAN_LONG: - $julian = new JulianCalendar; - return $julian->jdMonthName($julianday); + return self::jdMonthNameCalendar(self::$julian_calendar, $julian_day, self::$MONTH_NAMES); case CAL_MONTH_JULIAN_SHORT: - $julian = new JulianCalendar; - return $julian->jdMonthNameAbbreviated($julianday); + return self::jdMonthNameCalendar(self::$julian_calendar, $julian_day, self::$MONTH_NAMES_SHORT); case CAL_MONTH_JEWISH: - $jewish = new JewishCalendar; - return $jewish->jdMonthName($julianday); + return self::jdMonthNameCalendar(self::$jewish_calendar, $julian_day, self::jdMonthNameJewishMonths($julian_day)); case CAL_MONTH_FRENCH: - $french = new FrenchCalendar; - return $french->jdMonthName($julianday); + return self::jdMonthNameCalendar(self::$french_calendar, $julian_day, self::$MONTH_NAMES_FRENCH); - default: // CAL_MONTH_GREGORIAN_SHORT and anything else - $gregorian = new GregorianCalendar; - return $gregorian->jdMonthNameAbbreviated($julianday); + case CAL_MONTH_GREGORIAN_SHORT: + default: + return self::jdMonthNameCalendar(self::$gregorian_calendar, $julian_day, self::$MONTH_NAMES_SHORT); } } /** - * Converts a Julian Day Count to the French Republican Calendar. + * Calculate the month-name for a given julian day, in a given calendar, + * with given set of month names. * - * Shim implementation of \JDToFrench() + * @param CalendarInterface $calendar + * @param int $julian_day + * @param string[] $months * - * @link https://php.net/JDToFrench + * @return string + */ + private static function jdMonthNameCalendar(CalendarInterface $calendar, $julian_day, $months) { + list(, $month) = $calendar->jdToYmd($julian_day); + + return $months[$month]; + } + + /** + * Determine which month names to use for the Jewish calendar. * - * @param int $juliandaycount A Julian Day number + * @param int $julian_day * - * @return string A string of the form "month/day/year" + * @return string[] */ - public static function jdToFrench($juliandaycount) { - if ($juliandaycount >= FrenchCalendar::JD_START && $juliandaycount <= FrenchCalendar::JD_END) { - $french = new FrenchCalendar; - $cal = $french->calFromJd($juliandaycount); + private static function jdMonthNameJewishMonths($julian_day) { + list(, , $year) = explode('/', self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846)); - return $cal['date']; + if (self::$jewish_calendar->isLeapYear($year)) { + return self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH_LEAP_YEAR; + } else { + return self::shouldEmulateBug54254() ? self::$MONTH_NAMES_JEWISH_54254 : self::$MONTH_NAMES_JEWISH; + } + } + + /** + * Convert a Julian day in a specific calendar to a day/month/year. + * + * Julian days outside the specified range are returned as “0/0/0”. + * + * @param CalendarInterface $calendar + * @param int $julian_day + * @param int $min_jd + * @param int $max_jd + * + * @return string + */ + private static function jdToCalendar($calendar, $julian_day, $min_jd, $max_jd) { + if ($julian_day >= $min_jd && $julian_day <= $max_jd) { + list($year, $month, $day) = $calendar->jdToYmd($julian_day); + + return $month . '/' . $day . '/' . $year; } else { return '0/0/0'; } } /** + * Converts a Julian Day Count to the French Republican Calendar. + * + * Shim implementation of JDToFrench() + * + * @link https://php.net/JDToFrench + * + * @param int $julian_day A Julian Day number + * + * @return string A string of the form "month/day/year" + */ + public static function jdToFrench($julian_day) { + // JDToFrench() converts years 1 to 14 inclusive, even though the calendar + // officially ended on 10 Nivôse 14 (JD 2380687, 31st December 1805 Gregorian). + return self::jdToCalendar(self::$french_calendar, $julian_day, 2375840, 2380952); + } + + /** * Converts Julian Day Count to Gregorian date. * - * Shim implementation of \JDToGregorian() + * Shim implementation of JDToGregorian() * * @link https://php.net/JDToGregorian * - * @param int $julianday A Julian Day number + * @param int $julian_day A Julian Day number * * @return string A string of the form "month/day/year" */ - public static function jdToGregorian($julianday) { - $gregorian = new GregorianCalendar; - $cal = $gregorian->calFromJd($julianday); + 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 $cal['date']; + return self::jdToCalendar(self::$gregorian_calendar, $julian_day, 1, $MAX_JD); } /** * Converts a Julian day count to a Jewish calendar date. * - * Shim implementation of \JdtoJjewish() + * Shim implementation of JdtoJjewish() * * @link https://php.net/JdtoJewish * - * @param int $juliandaycount A Julian Day number - * @param bool $hebrew If true, the date is returned in Hebrew text - * @param int $fl If $hebrew is true, then add alafim and gereshayim to the text + * @param int $julian_day A Julian Day number + * @param bool $hebrew If true, the date is returned in Hebrew text + * @param int $fl If $hebrew is true, then add alafim and gereshayim to the text * * @return string A string of the form "month/day/year" */ - public static function jdToJewish($juliandaycount, $hebrew, $fl) { - $jewish = new JewishCalendar; - + public static function jdToJewish($julian_day, $hebrew, $fl) { if ($hebrew) { - if ($juliandaycount < 347998 || $juliandaycount > 4000075) { + if ($julian_day < 347998 || $julian_day > 4000075) { return trigger_error('Year out of range (0-9999).', E_USER_WARNING); } - $hebrew = $jewish->jdToHebrew($juliandaycount, $fl & CAL_JEWISH_ADD_ALAFIM_GERESH, $fl & CAL_JEWISH_ADD_ALAFIM, $fl & CAL_JEWISH_ADD_GERESHAYIM); - // Our code generates Hebrew punctuation. PHP uses ASCII punctuation. - $hebrew = strtr($hebrew, array(JewishCalendar::GERESH => "'", JewishCalendar::GERSHAYIM => '"')); - // Our code generates UTF-8. PHP generates ISO-8859=8 - $hebrew = mb_convert_encoding($hebrew, 'ISO-8859-8', 'UTF-8'); - return $hebrew; + return self::$jewish_calendar->jdToHebrew($julian_day, $fl & CAL_JEWISH_ADD_ALAFIM_GERESH, $fl & CAL_JEWISH_ADD_ALAFIM, $fl & CAL_JEWISH_ADD_GERESHAYIM); } else { - list($year, $month, $day) = $jewish->jdToYmd($juliandaycount); - - return $month . '/' . $day . '/' . $year; + // The upper limit is hard-coded into PHP to prevent numeric overflow on 32 bit systems. + return self::jdToCalendar(self::$jewish_calendar, $julian_day, 347998, 324542846); } } /** * Converts a Julian Day Count to a Julian Calendar Date. * - * Shim implementation of \JDToJulian() + * Shim implementation of JDToJulian() * * @link https://php.net/JDToJulian * - * @param int $julianday A Julian Day number + * @param int $julian_day A Julian Day number * * @return string A string of the form "month/day/year" */ - public static function jdToJulian($julianday) { - $julian = new JulianCalendar; - $cal = $julian->calFromJd($julianday); + public static function jdToJulian($julian_day) { + // PHP has different limits on 32 and 64 bit systems. + $MAX_JD = PHP_INT_SIZE == 4 ? 536838829 : 784368370349; - return $cal['date']; + return self::jdToCalendar(self::$julian_calendar, $julian_day, 1, $MAX_JD); } /** * Convert Julian Day to Unix timestamp. * - * Shim implementation of \jdtounix() + * Shim implementation of jdtounix() * * @link https://php.net/jdtounix * - * @param int $jday + * @param int $julian_day * - * @return int + * @return false|int */ - public static function jdToUnix($jday) { - if ($jday >= 2440588 && $jday <= 2465343) { - return (int)($jday - 2440588) * 86400; + public static function jdToUnix($julian_day) { + if ($julian_day >= 2440588 && $julian_day <= 2465343) { + return (int)($julian_day - 2440588) * 86400; } else { return false; } @@ -504,7 +696,7 @@ class Shim { /** * Converts a date in the Jewish Calendar to Julian Day Count. * - * Shim implementation of \JewishToJD() + * Shim implementation of JewishToJD() * * @link https://php.net/JewishToJD * @@ -514,20 +706,18 @@ class Shim { * * @return int */ - public static function jewishToJD($month, $day, $year) { - if ($year == 0) { + public static function jewishToJd($month, $day, $year) { + if ($year <= 0) { return 0; } else { - $jewish = new JewishCalendar; - - return $jewish->ymdToJd($year, $month, $day); + return self::$jewish_calendar->ymdToJd($year, $month, $day); } } /** * Converts a Julian Calendar date to Julian Day Count. * - * Shim implementation of \JdToJulian() + * Shim implementation of JdToJulian() * * @link https://php.net/JdToJulian * @@ -541,29 +731,27 @@ class Shim { if ($year == 0) { return 0; } else { - $julian = new JulianCalendar; - - return $julian->ymdToJd($year, $month, $day); + return self::$julian_calendar->ymdToJd($year, $month, $day); } } /** * Convert Unix timestamp to Julian Day. * - * Shim implementation of \unixtojd() + * Shim implementation of unixtojd() * * @link https://php.net/unixtojd * * @param int $timestamp * - * @return int + * @return false|int */ public static function unixToJd($timestamp) { if ($timestamp < 0) { return false; } else { // Convert timestamp based on local timezone - return static::GregorianToJd(gmdate('n', $timestamp), gmdate('j', $timestamp), gmdate('Y', $timestamp)); + return self::GregorianToJd(gmdate('n', $timestamp), gmdate('j', $timestamp), gmdate('Y', $timestamp)); } } } diff --git a/library/fisharebest/ext-calendar/src/shims.php b/library/fisharebest/ext-calendar/src/shims.php index e3cf1df6dd..d0a5eee4ba 100644 --- a/library/fisharebest/ext-calendar/src/shims.php +++ b/library/fisharebest/ext-calendar/src/shims.php @@ -19,20 +19,16 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -use Fisharebest\ExtCalendar\FrenchCalendar; -use Fisharebest\ExtCalendar\GregorianCalendar; -use Fisharebest\ExtCalendar\JewishCalendar; -use Fisharebest\ExtCalendar\JulianCalendar; use Fisharebest\ExtCalendar\Shim; -define(FrenchCalendar::PHP_CALENDAR_NAME, FrenchCalendar::PHP_CALENDAR_NUMBER); -define(GregorianCalendar::PHP_CALENDAR_NAME, GregorianCalendar::PHP_CALENDAR_NUMBER); -define(JewishCalendar::PHP_CALENDAR_NAME, JewishCalendar::PHP_CALENDAR_NUMBER); -define(JulianCalendar::PHP_CALENDAR_NAME, JulianCalendar::PHP_CALENDAR_NUMBER); +define('CAL_GREGORIAN', 0); +define('CAL_JULIAN', 1); +define('CAL_JEWISH', 2); +define('CAL_FRENCH', 3); define('CAL_NUM_CALS', 4); define('CAL_DOW_DAYNO', 0); -define('CAL_DOW_SHORT', Shim::emulateBug67960() ? 1 : 2); -define('CAL_DOW_LONG', Shim::emulateBug67960() ? 2 : 1); +define('CAL_DOW_SHORT', Shim::shouldEmulateBug67960() ? 1 : 2); +define('CAL_DOW_LONG', Shim::shouldEmulateBug67960() ? 2 : 1); define('CAL_MONTH_GREGORIAN_SHORT', 0); define('CAL_MONTH_GREGORIAN_LONG', 1); define('CAL_MONTH_JULIAN_SHORT', 2); @@ -45,76 +41,185 @@ define('CAL_EASTER_ALWAYS_GREGORIAN', 2); define('CAL_EASTER_ALWAYS_JULIAN', 3); define('CAL_JEWISH_ADD_ALAFIM_GERESH', 2); define('CAL_JEWISH_ADD_ALAFIM', 4); -define('CAL_JEWISH_ADD_GERESHAYIM ', 8); +define('CAL_JEWISH_ADD_GERESHAYIM', 8); -function cal_days_in_month($calendar, $month, $year) { - return Shim::calDaysInMonth($calendar, $month, $year); +/** + * @param int $calendar_id + * @param int $month + * @param int $year + * + * @return int + */ +function cal_days_in_month($calendar_id, $month, $year) { + return Shim::calDaysInMonth($calendar_id, $month, $year); } -function cal_from_jd($jd, $calendar) { - return Shim::calFromJd($jd, $calendar); +/** + * @param int $julian_day + * @param int $calendar_id + * + * @return array + */ +function cal_from_jd($julian_day, $calendar_id) { + return Shim::calFromJd($julian_day, $calendar_id); } -function cal_info($calendar = -1) { - return Shim::calInfo($calendar); +/** + * @param int $calendar_id + * + * @return array + */ +function cal_info($calendar_id = -1) { + return Shim::calInfo($calendar_id); } -function cal_to_jd($calendar, $month, $day, $year) { - return Shim::calToJd($calendar, $month, $day, $year); +/** + * @param int $calendar_id + * @param int $month + * @param int $day + * @param int $year + * + * @return int + */ +function cal_to_jd($calendar_id, $month, $day, $year) { + return Shim::calToJd($calendar_id, $month, $day, $year); } +/** + * @param int $year + * + * @return int + */ function easter_date($year = null) { - return Shim::easterDate($year); + return Shim::easterDate($year ? $year : date('Y')); } -function easter_days($year=null, $method=CAL_EASTER_DEFAULT) { +/** + * @param int $year + * @param int $method + * + * @return int + */ +function easter_days($year = null, $method = CAL_EASTER_DEFAULT) { return Shim::easterDays($year ? $year : date('Y'), $method); } +/** + * @param int $month + * @param int $day + * @param int $year + * + * @return int + */ function FrenchToJD($month, $day, $year) { return Shim::FrenchToJD($month, $day, $year); } +/** + * @param int $month + * @param int $day + * @param int $year + * + * @return int + */ function GregorianToJD($month, $day, $year) { return Shim::GregorianToJD($month, $day, $year); } -function JDDayOfWeek($julianday, $mode = CAL_DOW_DAYNO) { - return Shim::JDDayOfWeek($julianday, $mode); +/** + * @param int $julian_day + * @param int $mode + * + * @return mixed + */ +function JDDayOfWeek($julian_day, $mode = CAL_DOW_DAYNO) { + return Shim::JDDayOfWeek($julian_day, $mode); } -function JDMonthName($julianday, $mode) { - return Shim::JDMonthName($julianday, $mode); +/** + * @param int $julian_day + * @param int $mode + * + * @return string + */ +function JDMonthName($julian_day, $mode) { + return Shim::JDMonthName($julian_day, $mode); } -function JDToFrench($juliandaycount) { - return Shim::JDToFrench($juliandaycount); +/** + * @param int $julian_day + * + * @return string + */ +function JDToFrench($julian_day) { + return Shim::JDToFrench($julian_day); } -function JDToGregorian($julianday) { - return Shim::JDToGregorian($julianday); +/** + * @param int $julian_day + * + * @return string + */ +function JDToGregorian($julian_day) { + return Shim::JDToGregorian($julian_day); } -function jdtojewish($juliandaycount, $hebrew = false, $fl = 0) { - return Shim::jdtojewish($juliandaycount, $hebrew, $fl); +/** + * @param int $julian_day + * @param bool $hebrew + * @param int $flags + * + * @return string + */ +function jdtojewish($julian_day, $hebrew = false, $flags = 0) { + return Shim::jdtojewish($julian_day, $hebrew, $flags); } -function JDToJulian($julianday) { - return Shim::JDToJulian($julianday); +/** + * @param int $julian_day + * + * @return string + */ +function JDToJulian($julian_day) { + return Shim::JDToJulian($julian_day); } -function jdtounix($jday) { - return Shim::jdtounix($jday); +/** + * @param int $julian_day + * + * @return int + */ +function jdtounix($julian_day) { + return Shim::jdtounix($julian_day); } +/** + * @param int $month + * @param int $day + * @param int $year + * + * @return int + */ function JewishToJD($month, $day, $year) { return Shim::JewishToJD($month, $day, $year); } +/** + * @param int $month + * @param int $day + * @param int $year + * + * @return int + */ function JulianToJD($month, $day, $year) { return Shim::JulianToJD($month, $day, $year); } +/** + * @param int $timestamp + * + * @return int + */ function unixtojd($timestamp = null) { return Shim::unixtojd($timestamp ? $timestamp : time()); } |
