23

For example the:

  1. 3rd Monday of January for Martin Luther King Day
  2. 3rd Monday of February for Presidents' Day (Washington's Birthday)
  3. Last Sunday of March for Easter
  4. Last Monday of May for Memorial Day

I am trying to get these dates, so that I can mark it on my calendar without manually putting everything for the years to come.


MODIFIED ANSWER!!

$curYir = date("Y");//current year

$MLK = date('Y-m-d', strtotime("january $curYir third monday")); //marthin luthor king day
$PD = date('Y-m-d', strtotime("february $curYir third monday")); //presidents day
$Est =  date('Y-m-d', easter_date($curYir))); // easter 
$MDay = date('Y-m-d', strtotime("may $curYir first monday")); // memorial day
//("may $curYir last monday") will give you the last monday of may 1967
//much better to determine it by a loop
      $eMDay = explode("-",$MDay);
      $year = $eMDay[0];
      $month = $eMDay[1];
      $day = $eMDay[2];

      while($day <= 31){
          $day = $day + 7;
      }
      if($day > 31)
      $day = $day - 7;

      $MDay = $year.'-'.$month.'-'.$day;
$LD = date('Y-m-d', strtotime("september $curYir first monday"));  //labor day
$CD = date('Y-m-d', strtotime("october $curYir third monday")); //columbus day
$TH = date('Y-m-d', strtotime("november $curYir first thursday")); // thanks giving 
//("november $curYir last thursday") will give you the last thursday of november 1967
//much better to determine it by a loop
      $eTH = explode("-",$TH);
      $year = $eTH[0];
      $month = $eTH[1];
      $day = $eTH[2];

      while($day <= 30){
          $day = $day + 7;
      }
      if($day > 30)
      //watch out for the days in the month November only have 30
      $day = $day - 7;

      $TH = $year.'-'.$month.'-'.$day;
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
telexper
  • 2,381
  • 8
  • 37
  • 66
  • 1
    Looks like this pear package does what you want http://pear.php.net/package/Date_Holidays/redirected –  Feb 16 '13 at 06:16

7 Answers7

15

You can leverage this function of php. strtotime

$currentYear = date("Y");

MLK Day -

echo date('Y-m-d', strtotime("third monday of january $currentYear"));

Presidents Day -

echo date('Y-m-d', strtotime("third monday/OD February $currentYear"));

Easter -

echo date('Y-m-d', strtotime("last sunday of march $currentYear"));

Memorial Day -

echo date('Y-m-d', strtotime("last monday of may $currentYear"));
Sanchit
  • 2,240
  • 4
  • 23
  • 34
  • 3
    Easter isn't always the last Monday in March. Better to use PHP's built in easter_date() function: http://php.net/manual/en/function.easter-date.php – Matt James Sep 25 '15 at 20:48
  • This doesn't always returns the desired date. Check @Steve-Isenberg comment – Javis May 10 '16 at 19:46
  • Optionally, if you just want the day for the current year you can shorten the above like so: Memorial Day - echo date('m-d', strtotime("last monday of march")); – TGates Feb 13 '18 at 19:43
  • 1
    Memorial Day = last monday of **may** – luenib Sep 28 '18 at 19:57
8

The strtotime function is useful here but it seems to have some peculiarities on how it interprets the English verbiage. Be sure to check your wording carefully and check your results.

For instance this seems like it should work, but it will return the last Monday in April ($currentYear = 2014)!

echo "Memorial Day " . date('F d, Y', strtotime("may $currentYear last monday")) . "<br />";

However, this phrasing will return the correct holiday for 2014.

echo "Memorial Day " . date('F d, Y', strtotime("last monday of May $currentYear")) . "<br />"; 

And this will give you the correct date for the holiday next year.

echo "Memorial Day " . date('F d, Y', strtotime("last monday of May $currentYear+1")) . "<br />";

The PHP doc page has additional comments on its use. Take care

RiggsFolly
  • 93,638
  • 21
  • 103
  • 149
5

This way worked for me.

function observed_date($holiday){
    $day = date("w", strtotime($holiday));
    if($day == 6) {
        $observed_date = $holiday -1;
    } elseif ($day == 0) {
        $observed_date = $holiday +1;
    } else {
        $observed_date = $holiday;
    }
    return $observed_date;
}

function get_holiday($holiday_name) {

    $currentYear = date('Y');

    switch ($holiday_name) {
        // New Years Day
        case "new_year":
            $holiday = observed_date(date('Ymd', strtotime("first day of january $currentYear")));
            break;
        // Martin Luther King, Jr. Day
        case "mlk_day":
            $holiday = date('Ymd', strtotime("january $currentYear third monday"));
            break;
        // President's Day
        case "presidents_day":
            $holiday = date('Ymd', strtotime("february $currentYear third monday"));
            break;
        // Memorial Day
        case "memorial_day":
            $holiday = (new DateTime("Last monday of May"))->format("Ymd");
            break;
        // Independence Day
        case "independence_day":
            $holiday = observed_date(date('Ymd', strtotime("july 4 $currentYear")));
            break;
        // Labor Day
        case "labor_day":
            $holiday = date('Ymd', strtotime("september $currentYear first monday"));
            break;
        // Columbus Day
        case "columbus_day":
            $holiday = date('Ymd', strtotime("october $currentYear second monday"));
            break;
        // Veteran's Day
        case "veterans_day":
            $holiday = observed_date(date('Ymd', strtotime("november 11 $currentYear")));
            break;
        // Thanksgiving Day
        case "thanksgiving_day":
            $holiday = date('Ymd', strtotime("november $currentYear fourth thursday"));
            break;
        // Christmas Day
        case "christmas_day":
        $holiday = observed_date(date('Ymd', strtotime("december 25 $currentYear")));
            break;

        default:
            $holiday = "";
            break;
    }
    return $holiday;

}

Then you can print out the holiday by calling the function echo get_holiday('new_year');

And the result for 2015 should be 20150101

Amen Ra
  • 2,843
  • 8
  • 47
  • 85
  • Are you forgetting easter? – Etienne Noël Feb 14 '16 at 02:39
  • 2
    Adding and subtracting 1 from dates that are in YYYYMMDD format is a bad idea: if the date happens to be the first day of the month, rolling back by 1 day will give you an invalid date. For example, 1/1/2011 (Near Year's Day) is a Saturday, and subtracting 1 from 20110101 gives you 20110100. Same if the holiday falls on the last day of the month which happens to be a Sunday: if you add 1 day, you'll end up with an invalid date. – kmoser Sep 13 '20 at 20:56
3

Solution for moving holydays in Germany: returns an array of 'Y-m-d' formated strings including good friday, easter monday, ascencion, and pentecost monday. A new DateTime object for easter ist created for each day to enhance readability.

function beweglicheFeiertage( int $year ):array
{
    //Karfreitag - good friday
    $return = array();
    $easterDate = DateTime::createFromFormat('U', easter_date($year) );
    $easterDate->modify('- 1 days');
    $return[] = $easterDate->format('Y-m-d');
    //Ostermontag easter monday
    $easterDate = DateTime::createFromFormat('U', easter_date($year) );
    $easterDate->modify('+ 2 day');
    $return[] = $easterDate->format('Y-m-d');
    //Himmelfahrt ascencion
    $easterDate = DateTime::createFromFormat('U', easter_date($year) );
    $easterDate->modify('+ 40 days');//go to Ascencionday
    $return[] = $easterDate->format('Y-m-d');
    //Pfingstmontag - pentecost monday
    $easterDate = DateTime::createFromFormat('U', easter_date($year) );
    $easterDate->modify('+ 51 days');//go to Pentecost Monday
    $return[] = $easterDate->format('Y-m-d');

    return $return;
}
Max
  • 2,561
  • 1
  • 24
  • 29
  • Adding and subtracting 1 from dates that are in YYYYMMDD format is a bad idea: if the date happens to be the first day of the month, rolling back by 1 day will give you an invalid date. For example, 1/1/2011 (Near Year's Day) is a Saturday, and subtracting 1 from 20110101 gives you 20110100. Same if the holiday falls on the last day of the month which happens to be a Sunday: if you add 1 day, you'll end up with an invalid date. – kmoser Sep 11 '20 at 00:27
  • 1
    That might be true for the date() functions. In the modify() method of Datetime however this is taken care of. – Max Sep 13 '20 at 07:02
  • 1
    My mistake, my comment was meant for the post above you by @Amen Ra. – kmoser Sep 13 '20 at 20:57
3

I created a function that calculates all the federal holidays (US), for any given year and returns them inside an array. I've tested it with several different years (from 2016 to 2024). Here is the code, please let me know if you find any miscalculations:

    //function that checks if a holiday lands on saturday/sunday and so we can move them to a friday/monday respectively
    private function getObservedDate($holidayDate){

        $dayofweek = date("w", strtotime($holidayDate));

        if ($dayofweek == 6) $holidayDate = date('m/d/Y', strtotime("$holidayDate - 1 days")); //saturday moves to friday
        else if ($dayofweek == 0)  $holidayDate = date('m/d/Y', strtotime("$holidayDate + 1 days"));  //sunday moves monday

        return $holidayDate;
    }


    //function that calculates the holidays for any given year
    private function getFederalHolidaysForYear($year){

        $NY = $this->getObservedDate( date('m/d/Y', strtotime("1/1/$year")) ); //new years day

        $MLK = $this->getObservedDate( date('m/d/Y', strtotime("third monday of january $year")) );  //martin luther king day

        $PD = $this->getObservedDate( date('m/d/Y', strtotime("third monday of february $year")) ); ; //presidents day

        $MDay = $this->getObservedDate( date('m/d/Y', strtotime("last monday of May $year")) ); //memorial day  

        $IDay = $this->getObservedDate( date('m/d/Y', strtotime("7/4/$year")) );  // independence day

        $LD = $this->getObservedDate( date('m/d/Y', strtotime("first monday of september $year")) ); //labor day

        $VD = $this->getObservedDate( date('m/d/Y', strtotime("11/11/$year")) ); //veterans day

        $ColD =$this->getObservedDate( date('m/d/Y', strtotime("second monday of october $year")) ); //columbus day   

        $TG = $this->getObservedDate( date('m/d/Y', strtotime("last thursday of november $year")) ); // thanksgiving       

        $CD = $this->getObservedDate( date('m/d/Y', strtotime("12/25/$year")) );  //christmas day 

        $nonWorkingDays = array();

        array_push($nonWorkingDays, $NY, $MLK, $PD, $MDay, $IDay, $LD, $ColD, $VD, $TG, $CD);

        return $nonWorkingDays;
    }
Ivan
  • 1,265
  • 11
  • 20
1

If you are willing to manually enter the dates here once and for all you can use my custom made function here. It's short, simple and fulfills everyone's necessities. You can modify it for yourself if you want. Also, if you can find a way to dynamically pass the dates in the array in the given format then you may choose to modify it that way. However, my function below is only suitable for those holidays which have STATIC dates. You may have to manually manage the holidays each year for which have DYNAMIC or VARYING days such as memorial day, labour day etc.

My Custom PHP Function

If you mean to check for International Holidays here is a function I wrote for it.

function checkHoliday($date){
  if(date('l', strtotime($date)) == 'Saturday'){
    return "Saturday";
  }else if(date('l', strtotime($date)) == 'Sunday'){
    return "Sunday";
  }else{
    $receivedDate = date('d M', strtotime($date));

    $holiday = array(
      '01 Jan' => 'New Year Day',
      '18 Jan' => 'Martin Luther King Day',
      '22 Feb' => 'Washington\'s Birthday',
      '05 Jul' => 'Independence Day',
      '11 Nov' => 'Veterans Day',
      '24 Dec' => 'Christmas Eve',
      '25 Dec' => 'Christmas Day',
      '31 Dec' => 'New Year Eve'
    );

    foreach($holiday as $key => $value){
      if($receivedDate == $key){
        return $value;
      }
    }
  }
}

And call it this way

$date = '01/01/2021';

echo checkHoliday($date);
Shubham Jha
  • 97
  • 10
0

I combined @Shubham Jha's and @Max's solutions and came up with this option:

    //Function to see  if a date is a federal holiday and out put holiday name or day name
function checkHoliday($date){
    $nyDay = date('d M', strtotime("1/1")); //new years day
    $mlkDay = date('d M', strtotime("third monday of january"));  //martin luther king day
    $wbDay = date('d M', strtotime("third monday of february")); ; //washingtons birthday
    $mDay = date('d M', strtotime("last monday of May")); //memorial day  
    $iDay = date('d M', strtotime("7/4"));  // independence day
    $lDay = date('d M', strtotime("first monday of september")); //labor day
    $vDay = date('d M', strtotime("11/11")); //veterans day
    $colDay =date('d M', strtotime("second monday of october")); //columbus day   
    $tDay = date('d M', strtotime("last thursday of november")); // thanksgiving       
    $cDay = date('d M', strtotime("12/25"));  //christmas day
    $receivedDate = date('d M', strtotime($date));

    $holiday = array(
      $nyDay => 'new year\'s day',
      $mlkDay => 'martin luther king Day',
      $wbDay => 'washington\'s birthday',
      $mDay => 'memorial day',
      $mDay => 'independance day',
      $lDay => 'labor day',
      $vDay => 'veterans day',
      $colDay => 'columbus day',
      $tDay => 'thanksgiving day',
      $cDay => 'christmas day',
    );

    foreach($holiday as $key => $value){
      if($receivedDate == $key){
        return $value;
      }
    }
    if($receivedDate) {
    return strtolower(date('l', strtotime($receivedDate)));
    }
}
//end checkHoliday function
andyanderso
  • 301
  • 2
  • 3