Ok - well - I can see your problem.... LOTS OF DUPLICATION of code and some very unnecessary calls to functions (which are pretty intensive funcs) and assignment operators.
I don't normally do this... but I have some time to spare... so lets go through your code and rewrite it to something resembling what I might have produced and see if we can't make it run a bit better. I'm not professing this is the best way to do it (being that I am still rubbing sleep from my eyes only having just got up), but I'll try me best...
$month = 12;
$year = 2002;
$day_count = date('t', mktime(0, 0, 0, $month, 1, $year));
$holiday = 25;
$arrMonth = array();
for ($day = 1; $day <= $day_count; $day++)
{
$arrValues = getdate(mktime(12, 0, 0, $month, $day, $year));
if (($arrValues['wday'] > 0) && ($arrValues['wday'] < 6) && ($day != $holiday))
{
$start_time = mktime(9, 0, 0, $month, $day, $year);
$end_time = mktime(17, 0, 0, $month, $day, $year);
for ($i = $start_time; $i <= $end_time; $i += 300)
{
$arrMonth[] = $i;
}
}
}
foreach ($arrMonth as $key => $val)
{
echo "$key --> $val -->";
echo date("l dS of F Y h:i:s A", $val);
echo "<br>\n";
}
Ok - several key points to note. Firstly.... you seemed to be looping through all the times for every day, even if that day was obviously a weekend or holiday. The code above does that check before we bother looping through the times for the day.
if (($arrValues['wday'] > 0) && ($arrValues['wday'] < 6) && ($day != $holiday))
An obvious enhancement to this would be to make $holiday an array of numbers with all the holidays for that month listed. You could then check whether the value existed in the array to see if it was a holiday.
Secondly, you seemed to be looping through every time for every day, even though you know you only wanted 9am till 5pm (this code could be easily modified to account for lunch breaks as well). So - we only go through timestamps for 9am - 5pm and get rid of unnecessary time scanning.
And my last major point is that you made an ENOURMOUS number of calls to the date function, when we can get all the info we require in one easy call to getdate. Then we can store this and reference it as required.
All in all, the script above runs and displays in about a second. I haven't done any actual tests for speed, but I am sure you'll find out the script time is negligable.
I'm not saying that the code above is perfect though... tbh I am not fond of all those mktime calls I put in. This could easily be changed to use one call to mktime at the top and all other calls could be changed to use some simple maths to add to this timestamp to get the next day (assuming simple facts like a day has 86400 seconds, and the number of seconds between 5pm and 9am are 57600 etc etc). This could possible speed it up some more... but I leave this for you to play with.
Hopefully the above will give you a good ground to work from.