I recently had to write a function that allows me to know if today is a holiday.
And in France, we have some holidays which depends on the easter date. Maybe this will be helpful to someone.
Just modify in the $holidays array the actual holidays dates of your country.
<?php
/**
* This function returns an array of timestamp corresponding to french holidays
*/
protected static function getHolidays($year = null)
{
if ($year === null)
{
$year = intval(date('Y'));
}
$easterDate = easter_date($year);
$easterDay = date('j', $easterDate);
$easterMonth = date('n', $easterDate);
$easterYear = date('Y', $easterDate);
$holidays = array(
// These days have a fixed date
mktime(0, 0, 0, 1, 1, $year), // 1er janvier
mktime(0, 0, 0, 5, 1, $year), // Fête du travail
mktime(0, 0, 0, 5, 8, $year), // Victoire des alliés
mktime(0, 0, 0, 7, 14, $year), // Fête nationale
mktime(0, 0, 0, 8, 15, $year), // Assomption
mktime(0, 0, 0, 11, 1, $year), // Toussaint
mktime(0, 0, 0, 11, 11, $year), // Armistice
mktime(0, 0, 0, 12, 25, $year), // Noel
// These days have a date depending on easter
mktime(0, 0, 0, $easterMonth, $easterDay + 2, $easterYear),
mktime(0, 0, 0, $easterMonth, $easterDay + 40, $easterYear),
mktime(0, 0, 0, $easterMonth, $easterDay + 50, $easterYear),
);
sort($holidays);
return $holidays;
}
?>
easter_date
(PHP 4, PHP 5)
easter_date — Retorna a data do sistema UNIX correspondente à meia-noite da Páscoa do ano especificado. Se nenhum ano tiver sido especificado, será assumido o ano atual.
Descrição
$ano
] )Retorna a data do sistema UNIX correspondente à meia-noite da Páscoa do ano especificado. Se nenhum ano tiver sido especificado, será assumido o ano atual.
À partir da versão 4.3.0 PHP, e se omitido
o parâmetro ano, o padrão assumido é o ano
atual de acordo com a hora local.
Aviso Esta função irá gerar um aviso se o ano está fora do padrão de datas do sistema UNIX (i.e. antes de 1970 ou após 2037).
Exemplo #1 easter_date() exemplo
<?php
echo date ("M-d-Y", easter_date(1999)); // Apr-04-1999
echo date ("M-d-Y", easter_date(2000)); // Apr-23-2000
echo date ("M-d-Y", easter_date(2001)); // Apr-15-2001
?>
A data da Páscoa foi definida pelo Conselho de Nicaea em DC325 como sendo o primeiro domingo após a primeira lua cheia que cai no equinócio da primavera ou depois dele. O equinócio geralmente cai perto do 21º de Março, logo, o cálculo resume-se à determinar a data da lua cheia e a data do seguinte domingo. O algoritmo usado aqui foi feito no ano 532 por Dionysius Exiguus. De acordo com o calendário "Julian" (para anos anterioris à 1753) um simples ciclo de 19-anos é usado para seguir as fases da lua. De acordo com o Calendário Gregoriano (para antes após 1753 - planejado por Clavius e por Lilius, e feito por Pope Gregory XIII em Outubro de 1582, e na Grã Bretanha e suas colônias em Setembro de 1752), duas correções fatoriais foram adicionadas para fazer o ciclo mais exato.
(O código é baseado em um programa feito em C por Simon Kershaw, <webmaster@ely.anglican.org>)
Veja easter_days() para calcular a Páscoa antes de 1970 ou após 2037.
To compute the correct Easter date for Eastern Orthodox Churches I made a function based on the Meeus Julian algorithm:
<?php
function orthodox_eastern($year) {
$a = $year % 4;
$b = $year % 7;
$c = $year % 19;
$d = (19 * $c + 15) % 30;
$e = (2 * $a + 4 * $b - $d + 34) % 7;
$month = floor(($d + $e + 114) / 31);
$day = (($d + $e + 114) % 31) + 1;
$de = mktime(0, 0, 0, $month, $day + 13, $year);
return $de;
}
?>
I found a problem with holidays timestamp computation and daylight saving time.
An article about it at http://goo.gl/76t31 (in french only, sorry).
In summary, this year (2013) easter begins before adding an hour for daylight saving time (occured sunday at 3:00). It means that if you do $easter + X, where x is a number of seconds equivalent to one day, 39 days or 50 days, the result is not equals to a midnight timestamp...
Here a function to check if a midnight timestamp is equals to an holiday :
function isHoliday( $ts ) {
// Licence : Creative Commons (BY)
// By Webpulser - http://goo.gl/76t31
$fixed_holidays = array( ’01-01′, ’01-05′, ’08-05′, ’14-07′, ’15-08′, ’11-11′, ’25-12′ );
$format = ‘d-m’;
$dm = date($format, $ts);
if ( in_array($dm, $fixed_holidays) ) return true;
$easter = easter_date( date(‘Y’, $ts) );
if ( date($format, $easter + 86400) == $dm ) return true;
if ( date($format, $easter + 3369600) == $dm ) return true;
if ( date($format, $easter + 4320000) == $dm ) return true;
return false;
}
feel free to use / modify.
Due to range limitations of core functions such as easter_date(), mktime(), strtotime(), I wrote this function to get the Easter Day in string format yyyy-mm-dd.
function myEaster($year)
{
/*Warning: easter_date(): This function is only valid for years between 1970 and 2037
* The easter_days() function can be used instead of easter_date() to calculate Easter for years which fall outside the range.
*/
//The next line would do the work if there were no limitations:
//return date("Y-m-d",easter_date($year));
/*Outside range (1970,2037) they advise to use easter_days().
* Unfortunately, when you have to create a date object as 21-03-yyyy to which add easter_days(), then obtain Easter,
* functions like strtotime(), DateTime::createFromFormat() will fail. (return value is 01-01-1970)
*/
$march21=date("$year-03-21");
$days=easter_days($year);
if($year<=2037)
//The next line would do the work if strtotime() wasn't affected by same limitations. But, the if..else is required to handle all years.
$date = date("Y-m-d",strtotime(date("Y-m-d", strtotime($march21)) . " +$days day"));
else
{
if($days<=10){
$day=str_pad(21+$days, 2, '0', STR_PAD_LEFT);
$date=date("$year-03-$day");
}
else
{
$day=str_pad($days-10, 2, '0', STR_PAD_LEFT);
$date=date("$year-04-$day");
}
}
return $date;
}
In 5.3.1 easter_date() returns GMT of start of Easter Day in UK allowing
for UK Summer Time. If you are in another time zone you need to
calculate offsets.
<?php
$e1 = easter_date(2008);
$e2 = easter_date(2009);
echo "Timestamps " . $e1 . " " . $e2 . "\n";
// Timestamps 1206230400 1239490800
echo "Days between Easter 2008 Easter 2009 = " . ($e2-$e1)/86400 . "\n";
// Days between Easter 2008 Easter 2009 = 384.958333333 - i.e. 384 days 23 hours
date_default_timezone_set("Europe/London");
echo date( " l, jS F Y H:i TO",$e1) . "\n";
echo date( " l, jS F Y H:i TO",$e2) . "\n";
// Sunday, 23rd March 2008 00:00 GMT+0000
// Sunday, 12th April 2009 00:00 BST+0100
date_default_timezone_set("America/New_York");
echo date( " l, jS F Y H:i TO",$e1) . "\n";
echo date( " l, jS F Y H:i TO",$e2) . "\n";
// Saturday, 22nd March 2008 20:00 EDT-0400
// Saturday, 11th April 2009 19:00 EDT-0400
// Daylight saving time in effect - New York 4 hours behind GMT
?>
v5.2.1 - There is a known bug with easter_date() that can return incorrect dates for some years:
<?php
// 2008 OK
echo date("D d M Y", easter_date(2008)); // Sun 23 Mar 2008
// 2009 returns Saturday
echo date("D d M Y", easter_date(2009)); // Sat 11 Apr 2009
?>
However easter_days() works correctly:
<?php
echo date("D d M Y", strtotime("2009-03-21 +".easter_days(2009)." days")); // Sun 12 Apr 2009
?>
It is apparently related to timezone settings.
I made the function like this ... works fine !
<?php
function ostern
{
$maerz21=date('z',mktime(0,0,0,3,21,$jb));
$d=((15 + $jb/100 - $jb/400 - (8 * $jb/100 + 13) / 25)%30 + 19 * ($jb%19))%30;
if ($d==29)
{
$D=28;
}
elseif($d==28 && ($jb%17)>=11)
{
$D=27;
}
else $D=$d;
$e=(2 * ($jb%4) + 4 *($jb%7) + 6 * $D + (6 + $jb/100 - $jb/400 - 2)%7)%7;
$ostersonntag=$e+$D+1+$maerz21;
return $ostersonntag;
}
?>
The algorithm from Bigtree is correct if you add some (int) cast
<?php
function easter_date ($Year) {
/*
G is the Golden Number-1
H is 23-Epact (modulo 30)
I is the number of days from 21 March to the Paschal full moon
J is the weekday for the Paschal full moon (0=Sunday,
1=Monday, etc.)
L is the number of days from 21 March to the Sunday on or before
the Paschal full moon (a number between -6 and 28)
*/
$G = $Year % 19;
$C = (int)($Year / 100);
$H = (int)($C - (int)($C / 4) - (int)((8*$C+13) / 25) + 19*$G + 15) % 30;
$I = (int)$H - (int)($H / 28)*(1 - (int)($H / 28)*(int)(29 / ($H + 1))*((int)(21 - $G) / 11));
$J = ($Year + (int)($Year/4) + $I + 2 - $C + (int)($C/4)) % 7;
$L = $I - $J;
$m = 3 + (int)(($L + 40) / 44);
$d = $L + 28 - 31 * ((int)($m / 4));
$y = $Year;
$E = mktime(0,0,0, $m, $d, $y);
return $E;
}
?>
