Source for file Driver.php
Documentation is available at Driver.php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Carsten Lucke <luckec@tool-garage.de> |
// +----------------------------------------------------------------------+
// $Id: Driver.php,v 1.20 2006/04/03 21:04:46 luckec Exp $s
require_once 'PEAR/ErrorStack.php';
require_once 'Date/Holidays/Filter.php';
require_once 'Date/Holidays/Filter/Whitelist.php';
require_once 'Date/Holidays/Filter/Blacklist.php';
define('DATE_HOLIDAYS_INVALID_INTERNAL_NAME', 51 );
* title for a holiday is not available
define('DATE_HOLIDAYS_TITLE_UNAVAILABLE', 52 );
* date could not be converted into a PEAR::Date object
* date was neither a timestamp nor a string
* @deprecated will certainly be removed
define('DATE_HOLIDAYS_INVALID_DATE', 53 );
* string that represents a date has wrong format
* format must be YYYY-MM-DD
* @deprecated will certainly be removed
define('DATE_HOLIDAYS_INVALID_DATE_FORMAT', 54 );
* date for a holiday is not available
define('DATE_HOLIDAYS_DATE_UNAVAILABLE', 55 );
* language-file doesn't exist
define('DATE_HOLIDAYS_LANGUAGEFILE_NOT_FOUND', 56 );
* unable to read language-file
define('DATE_HOLIDAYS_UNABLE_TO_READ_TRANSLATIONDATA', 57 );
* Name of the static {@link Date_Holidays_Driver} method returning
* a array of possible ISO3166 codes that identify itself.
define('DATE_HOLIDAYS_DRIVER_IDENTIFY_ISO3166_METHOD', 'getISO3166Codes');
* class that helps you to locate holidays for a year
* @version $Id: Driver.php,v 1.20 2006/04/03 21:04:46 luckec Exp $
* @author Carsten Lucke <luckec@tool-garage.de>
* locale setting for output
* locales for which translations of holiday titles are available
var $_availableLocales = array ('C');
* internal names for the available holidays
* dates of the available holidays
* array of the available holidays indexed by date
* localized names of the available holidays
* Array of holiday-properties indexed by internal-names and furthermore by locales.
* $_holidayProperties = array(
* 'internalName1' => array(
* 'internalName2' => array(
var $_holidayProperties = array ();
* Use the Date_Holidays::factory() method to construct an object of a certain driver
* Method that returns an array containing the ISO3166 codes that may possibly
* @return array possible ISO3166 codes
* Sets the driver's current year
* Calling this method forces the object to rebuild the holidays
* @return boolean true on success, otherwise a PEAR_ErrorStack object
* @throws object PEAR_ErrorStack
* Returns the driver's current year
* @return int current year
* Build the internal arrays that contain data about the calculated holidays
* @return boolean true on success, otherwise a PEAR_ErrorStack object
* @throws object PEAR_ErrorStack
* @param object Date_Holidays_Driver $driver driver-object
* Remove a driver component
* @param object Date_Holidays_Driver $driver driver-object
* @return boolean true on success, otherwise a PEAR_Error object
* @throws object PEAR_Error DATE_HOLIDAYS_DRIVER_NOT_FOUND
* Returns the internal names of holidays that were calculated
* Returns localized titles of all holidays or those accepted by the filter
* @param Date_Holidays_Filter filter-object (or an array !DEPRECATED!)
* @param string $locale locale setting that shall be used by this method
* @return array array with localized holiday titles on success, otherwise a PEAR_Error object
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
* @uses getHolidayTitle()
if ($filter->accept ($internalName)) {
$titles[$internalName] = $title;
* Returns localized title for a holiday
* @param string $internalName internal name for holiday
* @param string $locale locale setting that shall be used by this method
* @return string title on success, otherwise a PEAR_Error object
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME, DATE_HOLIDAYS_TITLE_UNAVAILABLE
if (! isset ($this->_titles[$locale][$internalName])) {
') for the holiday was correct but no localized title could be found');
return isset ($this->_titles[$locale][$internalName]) ?
$this->_titles[$locale][$internalName] : $this->_titles['C'][$internalName];
* Returns the localized properties of a holiday. If no properties have been stored an empty
* array will be returned.
* @param string $internalName internal name for holiday
* @param string $locale locale setting that shall be used by this method
* @return array array of properties on success, otherwise a PEAR_Error object
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
if (isset ($this->_holidayProperties[$internalName][$locale])) {
$properties = $this->_holidayProperties[$internalName][$locale];
* Returns all holidays that the driver knows.
* You can limit the holidays by passing a filter, then only those
* holidays accepted by the filter will be returned.
* 'easter' => object of type Date_Holidays_Holiday,
* 'eastermonday' => object of type Date_Holidays_Holiday,
* @param Date_Holidays_Filter $filter filter-object (or an array !DEPRECATED!)
* @param string $locale locale setting that shall be used by this method
* @return array numeric array containing objects of Date_Holidays_Holiday on success,
* otherwise a PEAR_Error object
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
if ($filter->accept ($internalName)) {
// no need to check for valid internal-name, will be done by #getHoliday()
$holidays[$internalName] = $this->getHoliday($internalName, $locale);
* Returns the specified holiday
* 'title' => 'Easter Sunday'
* @param string $internalName internal name of the holiday
* @param string $locale locale setting that shall be used by this method
* @return object Date_Holidays_Holiday holiday's information on success, otherwise a PEAR_Error object
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
* @uses getHolidayTitle()
function getHoliday($internalName, $locale = null )
'Invalid internal name: ' . $internalName);
* Determines whether a date represents a holiday or not
* @param mixed $date date (can be a timestamp, string or PEAR::Date object)
* @param Date_Holidays_Filter $filter filter-object (or an array !DEPRECATED!)
* @return boolean true if date represents a holiday, otherwise false
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE, DATE_HOLIDAYS_INVALID_DATE_FORMAT
if (! is_a($date, 'Date')) {
$date = $this->_convertDate ($date);
if ($filter->accept ($internalName)) {
$date, $this->_dates[$internalName]) != 0 ) {
* Returns a <code>Date_Holidays_Holiday</code> object, if any was found,
* matching the specified date.
* Normally the method will return the object of the first holiday matching the date.
* If you want the method to continue searching holidays for the specified date,
* set the 4th param to true.
* If multiple holidays match your date, the return value will be an array containing a number
* of <code>Date_Holidays_Holiday</code> items.
* @param mixed $date date (timestamp | string | PEAR::Date object)
* @param string $locale locale setting that shall be used by this method
* @param boolean $multiple
* @return object object of type Date_Holidays_Holiday on success
* (numeric array of those on multiple search),
* if no holiday was found, matching this date, null is returned
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE, DATE_HOLIDAYS_INVALID_DATE_FORMAT
* @uses getHolidayTitle()
if (!is_a($date, 'Date')) {
$date = $this->_convertDate ($date);
$isodate = mktime(0 , 0 , 0 , $date->getMonth (), $date->getDay (), $date->getYear ());
//get only the first feast for this day
$internalName = $this->_holidays[$isodate][0 ];
$result = $this->getHoliday($internalName, $locale);
// array that collects data, if multiple searching is done
foreach($this->_holidays[$isodate] as $internalName) {
$result = $this->getHoliday($internalName, $locale);
* Returns an array containing a number of <code>Date_Holidays_Holiday</code> items.
* If no items have been found the returned array will be empty.
* @param mixed $start date (timestamp | string | PEAR::Date object)
* @param mixed $end date (timestamp | string | PEAR::Date object)
* @param Date_Holidays_Filter $filter filter-object (or an array !DEPRECATED!)
* @param string $locale locale setting that shall be used by this method
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE, DATE_HOLIDAYS_INVALID_DATE_FORMAT
* @return array an array containing a number of <code>Date_Holidays_Holiday</code> items
if (!is_a($start, 'Date')) {
$start = $this->_convertDate ($start);
if (!is_a($end, 'Date')) {
$end = $this->_convertDate ($end);
$isodateStart = mktime(0 , 0 , 0 , $start->getMonth (), $start->getDay (),
$isodateEnd = mktime(0 , 0 , 0 , $end->getMonth (), $end->getDay (), $end->getYear ());
$internalNames = array ();
foreach ($this->_holidays as $isoDateTS => $arHolidays) {
if ($isoDateTS >= $isodateStart && $isoDateTS <= $isodateEnd) {
$internalNames = array_merge($internalNames, $arHolidays);
foreach ($internalNames as $internalName) {
if ($filter->accept ($internalName)) {
$retval[] = $this->getHoliday($internalName, $locale);
* Converts timestamp or date-string into da PEAR::Date object
* @param mixed $date date
* @return object PEAR_Date
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE, DATE_HOLIDAYS_INVALID_DATE_FORMAT
function _convertDate ($date)
if (! preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}/', $date)) {
'Date-string has wrong format (must be YYYY-MM-DD)');
$date = new Date (date('Y-m-d', $date));
'The date you specified is invalid');
* Adds all holidays in the array to the driver's internal list of holidays.
* 'newYearsDay' => array(
* 'title' => 'New Year\'s Day',
* 'translations' => array(
* 'en_EN' => 'New Year\'s Day'
* 'valentinesDay' => array(
* @param array $holidays static holidays' data
foreach ($holidays as $internalName => $holiday) {
// add the holiday's basic data
$this->_addHoliday($internalName, $this->_year . '-' . $holiday['date'], $holiday['title']);
* Adds a holiday to the driver's holidays
* @param string $internalName internal name - must not contain characters that aren't allowed as variable-names
* @param mixed $date date (timestamp | string | PEAR::Date object)
* @param string $title holiday title
if (! is_a($date, 'Date')) {
$this->_dates[$internalName] = $date;
$this->_titles['C'][$internalName] = $title;
$isodate = mktime(0 , 0 , 0 , $date->getMonth (), $date->getDay (), $date->getYear ());
* Add a localized translation for a holiday's title. Overwrites existing data.
* @param string $internalName internal name of an existing holiday
* @param string $locale locale setting that shall be used by this method
* @param string $title title
* @return true on success, otherwise a PEAR_Error object
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
'Couldn\'t add translation (' . $locale . ') for holiday with this internal name: ' . $internalName);
if (! in_array($locale, $this->_availableLocales)) {
$this->_titles[$locale][$internalName] = $title;
* Adds a localized (regrading translation etc.) string-property for a holiday.
* Overwrites existing data.
* @param string internal-name
* @param string locale-setting
* @param string property-identifier
* @param mixed property-value
* @return boolean true on success, false otherwise
* @throws PEAR_ErrorStack if internal-name does not exist
'Couldn\'t add property (locale: ' . $locale . ') for holiday with this internal name: ' . $internalName);
if (!isset ($this->_holidayProperties[$internalName]) ||
!is_array($this->_holidayProperties[$internalName])) {
$this->_holidayProperties[$internalName] = array ();
if (! isset ($this->_holidayProperties[$internalName][$locale]) ||
!is_array($this->_holidayProperties[$internalName][$locale])) {
$this->_holidayProperties[$internalName][$locale] = array ();
$this->_holidayProperties[$internalName][$locale][$propId] = $propVal;
* Adds a arbitrary number of localized string-properties for the specified holiday.
* @param string internal-name
* @param string locale-setting
* @param array associative array: array(propId1 => value1, propid2 => value2, ...)
* @return boolean true on success, false otherwise
* @throws PEAR_ErrorStack if internal-name does not exist
foreach ($properties as $propId => $propValue) {
* Add a language-file's content
* The language-file's content will be parsed and translations, properties, etc. for
* holidays will be made available with the specified locale.
* @param string $file filename of the language file
* @param string $locale locale-code of the translation
* @return boolean true on success, otherwise a PEAR_ErrorStack object
* @throws object PEAR_Errorstack
'Language-file not found: ' . $file);
require_once 'XML/Unserializer.php';
'parseAttributes' => false ,
'attributesArray' => false ,
'keyAttribute' => array ('property' => 'id'),
'forceEnum' => array ('holiday')
$unserializer = new XML_Unserializer ($options);
// unserialize the document
$status = $unserializer->unserialize ($file, true );
if (PEAR ::isError ($status)) {
$content = $unserializer->getUnserializedData ();
* Add a compiled language-file's content
* The language-file's content will be unserialized and translations, properties, etc. for
* holidays will be made available with the specified locale.
* @param string $file filename of the compiled language file
* @param string $locale locale-code of the translation
* @return boolean true on success, otherwise a PEAR_ErrorStack object
* @throws object PEAR_Errorstack
'Language-file not found: ' . $file);
if ($content === false ) {
'Unable to read translation-data - file maybe damaged: ' . $file);
* Add a language-file's content. Translations, properties, etc. for
* holidays will be made available with the specified locale.
* @param array $data translated data
* @param string $locale locale-code of the translation
* @return boolean true on success, otherwise a PEAR_ErrorStack object
* @throws object PEAR_Errorstack
foreach ($data['holidays']['holiday'] as $holiday) {
$holiday['translation']);
if (isset ($holiday['properties']) && is_array($holiday['properties'])) {
foreach ($holiday['properties'] as $propId => $propVal) {
* Remove a holiday from internal storage
* This method should be used within driver classes to unset holidays that were inherited from
* @param $string $internalName internal name
* @return boolean true on success, otherwise a PEAR_Error object
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
'Couldn\'t remove holiday with this internal name: ' . $internalName);
if (isset ($this->_dates[$internalName])) {
unset ($this->_dates[$internalName]);
foreach ($locales as $locale) {
if (isset ($this->_titles[$locale][$internalName])) {
unset ($this->_titles[$locale][$internalName]);
* Finds the best internally available locale for the specified one
* @param string $locale locale
* @return string best locale available
/* exact locale is available */
if (in_array($locale, $this->_availableLocales)) {
/* first two letter are equal */
foreach ($this->_availableLocales as $aLocale) {
/* no appropriate locale available, will use driver's internal locale */
* Returns date of a holiday
* @param string $internalName internal name for holiday
* @return object Date date of the holiday as PEAR::Date object on success, otherwise a PEAR_Error object
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME, DATE_HOLIDAYS_DATE_UNAVAILABLE
if (! isset ($this->_dates[$internalName])) {
return $this->_dates[$internalName];
* Returns dates of all holidays or those accepted by the applied filter.
* Structure of the returned array:
* 'internalNameFoo' => object of type date,
* 'internalNameBar' => object of type date
* @param Date_Holidays_Filter filter-object (or an array !DEPRECATED!)
* @return array with holidays' dates on success, otherwise a PEAR_Error object
* @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
if ($filter->accept ($internalName)) {
* Sets the driver's locale
* @param string $locale locale
* Sloppily compares two date objects (only year, month and day are compared).
* Does not take the date's timezone into account.
* @param Date $d1 a date object
* @param Date $d2 another date object
* @return int 0 if the dates are equal, -1 if d1 is before d2, 1 if d1 is after d2
function dateSloppyCompare ($d1, $d2)
$d1->setTZ (new Date_TimeZone ('UTC'));
$d2->setTZ (new Date_TimeZone ('UTC'));
$days1 = Date_Calc ::dateToDays ($d1->day , $d1->month , $d1->year );
$days2 = Date_Calc ::dateToDays ($d2->day , $d2->month , $d2->year );
if ($days1 < $days2) return -1;
if ($days1 > $days2) return 1;
Documentation generated on Mon, 11 Mar 2019 15:03:07 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|