<?php
/*
USA Daylight Saving Time Schedule Calculator
Author:
Jay Tanner - 2023
www.Neoprogrammics.com
Development Language:
PHP 5.x to PHP v7.4.9
License:
Public Domain
THIS PROGRAM COMPUTES THE START AND END OF DAYLIGHT SAVING
TIME FOR ANY GIVEN YEAR SINCE 1975.
PREVIOUS DAYLIGHT SAVING RULE (1986 to 2006)
First Sunday in April to last Sunday in October
NEW DAYLIGHT SAVING RULE (As of 2007):
Second Sunday in March to first Sunday in November.
The result of the change was to change the starting date of
Daylight Saving Time to 3 weeks earlier than before, to the
second Sunday in March and also change the ending date to one
week later than before, to the first Sunday in November.
This change hereafter adds one month (4 weeks) more of daylight
saving time to the calendar than before.
*/
// Initialize for cookies
ob_start();
$cYear = gmdate("Y");
$_PROGRAM_VERSION_ = '';
$DiffDays = "0";
$DurationStr = "";
$_COOKIE_NAME_ = "USA_Daylight_Saving_Time_Calculator";
$_SCRIPT_PATH_ = $_SERVER['SCRIPT_NAME'];
$_HTML_TITLE_ = "U.S.A. Daylight Saving Time Schedule Calculator";
$_HEADER_ = "U.S.A. Daylight Saving Time";
// ===========================================================
// Set cookie expiration date to 30 days.
//
// This value must be the number of seconds as measured from
// the moment the cookie is created. To set the cookie to
// expire in 30 days, simply multiply the number of days
// by 86400 seconds per day.
$ThirtyDays = 30 * 86400;
// Construct download link so that it only shows up
// when the program is posted on the public WWW. On
// the local desktop, the download link is supressed.
$_SCRIPT_PATH_ = Filter_Input(INPUT_SERVER, 'SCRIPT_FILENAME');
// =======================================
// Do this if "Submit" button was clicked.
if (IsSet($_POST["ComputeButton"]))
{
$y = trim(Filter_Input(INPUT_POST, 'y'));
if ($y == '') {$y = date('Y');}
$CookieDataString = $y;
setcookie ($_COOKIE_NAME_, $CookieDataString, time() + $ThirtyDays);
}
else
// ======================================================
// Do this if program was called externally via URL link.
{
// ========================================================
// If a cookie exists, then recall interface value from it.
if (IsSet($_COOKIE[$_COOKIE_NAME_]))
{
$y = $_COOKIE[$_COOKIE_NAME_];
}
else
// ===============================================
// If no cookie exists, then set default interface
// value and copy it to an initial cookie.
{
$y = gmdate('Y');
$CookieDataString = "$y";
setcookie ($_COOKIE_NAME_, $CookieDataString, time() + $ThirtyDays);
}
}
// **********************************
// **********************************
// AT THIS POINT, THE INPUT INTERFACE
// VALUES SHOULD BE READY FOR USE
// ---------------------------------------
// CHECK FOR AND BLOCK INVALID YEAR INPUT.
if ($y < 1975 or $y > 9999)
{
$DSTStartsCalendar = "<b style='font-size:150%;'>Invalid year.</b>";
$DSTEndsCalendar = "<b style='font-size:150%;'>Year must be 1975 or later.</b>";
$DSTRuleUsed = "<B style='color:red; font-size:150%;'>ERROR</B>";
}
else
// =============================
// CONTINUE BELOW IF YEAR IS OK.
// MAIN COMPUTATIONS START HERE
{
// DETERMINE WHICH RULE TO USE ACCORDING TO THE YEAR.
if ($y > 1974 and $y < 1987)
{
$DSTRuleUsed = "Starts on last Sunday in April at 02:00 AM Local Time - Spring ahead 1 hour<br><br>Ends on last Sunday in October at 02:00 AM Local Time - Fall back 1 hour<br><br>";
$ISOymd = Final_Sunday ($y, 4, 1);
$JDA = JD_For_ISOymd ($ISOymd);
$DSTStartsCalendar = "<B>U.S.A. Daylight Saving Time Start Date</B><br><br>\n" . Calendar_Table ($ISOymd, 1, "Yellow");
$DSTStartsCalendar = str_replace("G ", "", $DSTStartsCalendar);
$ISOymd = Final_Sunday ($y, 10, 1);
$JDB = JD_For_ISOymd ($ISOymd);
$DSTEndsCalendar = "<B>U.S.A. Daylight Saving Time End Date</B><BR><BR>\n" . Calendar_Table ($ISOymd, 1, "Cyan");
$DSTEndsCalendar = str_replace("G ", "", $DSTEndsCalendar);
$DiffDays = $JDB - $JDA;
$DurationWeeks = $DiffDays / 7;
$DurationStr = "Duration = $DiffDays days = $DurationWeeks weeks";
}
if ($y > 1986 and $y < 2007)
{
$DSTRuleUsed = "Starts on first Sunday in April at 02:00 AM Local Time - Spring ahead 1 hour<br><br>Ends on last Sunday in October at 02:00 AM Local Time - Fall back 1 hour<br><br>";
$ISOymd = nth_DoW_In_ym (1, 0, $y, 4, 1);
$JDA = JD_For_ISOymd ($ISOymd);
$DSTStartsCalendar = "<B>U.S.A. Daylight Saving Time Start Date</B><br><br>\n" . Calendar_Table ($ISOymd, 1, "Yellow");
$DSTStartsCalendar = str_replace("G ", "", $DSTStartsCalendar);
$ISOymd = Final_Sunday ($y, 10, 1);
$JDB = JD_For_ISOymd ($ISOymd);
$DSTEndsCalendar = "<B>U.S.A. Daylight Saving Time End Date</B><BR><BR>\n" . Calendar_Table ($ISOymd, 1, "Cyan");
$DSTEndsCalendar = str_replace("G ", "", $DSTEndsCalendar);
$DiffDays = $JDB - $JDA;
$DurationWeeks = $DiffDays / 7;
$DurationStr = "Duration = $DiffDays days = $DurationWeeks weeks";
}
if ($y > 2006)
{
$DSTRuleUsed = "Starts on second Sunday in March at 02:00 AM Local Time - Spring ahead 1 hour<br><br>Ends on first Sunday in November at 02:00 AM Local Time - Fall back 1 hour<br><br>";
$ISOymd = nth_DoW_In_ym (2, 0, $y, 3, 1);
$JDA = JD_For_ISOymd ($ISOymd);
$DSTStartsCalendar = "<B>U.S.A. Daylight Saving Time Start Date</B><br><br>\n" . Calendar_Table ($ISOymd, 1, "Yellow");
$DSTStartsCalendar = str_replace("G ", "", $DSTStartsCalendar);
$ISOymd = nth_DoW_In_ym (1, 0, $y, 11, 1);
$JDB = JD_For_ISOymd ($ISOymd);
$DSTEndsCalendar = "<B>U.S.A. Daylight Saving Time End Date</B><BR><BR>\n" . Calendar_Table ($ISOymd, 1, "Cyan");
$DSTEndsCalendar = str_replace("G ", "", $DSTEndsCalendar);
$DiffDays = $JDB - $JDA;
$DurationWeeks = $DiffDays / 7;
$DurationStr = "Duration = $DiffDays days = $DurationWeeks weeks";
}
// =====================================
// CONSTRUCT FORMATTED TEXT OUTPUT BLOCK
$out = " y = $y\n";
}
// =========================================================
// DYNAMIC W3C COMPLIANT HTML DOCUMENT OUTPUT FOLLOWS BELOW.
print <<< _HTML
<!DOCTYPE HTML>
<HTML>
<HEAD>
<TITLE>U.S.A. Daylight Saving Time Schedule Calculator</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<meta name='viewport' content='width=device-width, initial-scale=1'>
<meta http-equiv='content-type' content='text/html; charset=UTF-8'>
<meta name='description' content='USA Daylight Saving Time Schedule Calculator For Any Year'>
<meta name='keywords' content='summer time, daylight saving time'>
<meta name='author' content='Jay Tanner - PHP Science Labs'>
<meta http-equiv='pragma' content='no-cache'>
<meta http-equiv='expires' content='-1'>
<meta name='robots' content='index,follow'>
<meta name='googlebot' content='index,follow'>
<link rel="canonical" href="https://www.phpsciencelabs.com/usa-daylight-saving-time-schedule-calculator/">
<style type='text/css'>
BODY
{
margin: 4px 4px 4px 4px; /* Adjust for optional logo */
color: black;
font-family: Verdana;
font-size: 12px;
font-weight: normal;
word-spacing: normal;
letter-spacing: normal;
line-height: 150%;
padding: 2px;
}
div {padding: 4px 4px 4px 4px;}
::selection{background-color:yellow !important; color:black !important;}
::-moz-selection{background-color:yellow !important; color:black !important;}
input[type="text"]::-ms-clear {width:0; height:0;}
input[type="text"] {background-color:white; box-shadow:2px 2px 3px #666666; font-family:monospace; font-size:150%; font-weight:bold; text-align:center; border:2px solid black;}
input[type="text"]:focus {background-color:white; box-shadow:2px 2px 3px #666666; font-family:monospace; font-size:150%; border:2px solid red; text-align:center; font-weight:bold;}
input[type="submit"]:hover {box-shadow:2px 2px 5px #222222; font-weight:bold;}
A:link, A:visited {background-color:transparent; color:blue; font-family:Verdana; font-size:12px; font-weight:bold; text-decoration:none; line-height:150%; padding:2px;}
A:hover, A:active {background-color:transparent; color:red; font-family:Verdana; font-size:12px; font-weight:bold; text-decoration:none; line-height:150%; padding:2px;}
</style>
</HEAD>
<BODY BGCOLOR="black">
<FORM NAME="InputForm1" METHOD="post" ACTION="">
<table align='left' width="666" border="0" align="bottom" bgcolor="black" cellpadding="4" cellspacing="1">
<TR><TD style='color:white; background-color:#000066; text-align:center; border:2px solid white; border-radius:8px 8px 0px 0px; font-size:150%; line-height:150%;'><B style='font-weight:normal;'>U.S.A. Daylight Saving Time Schedule Calculator</B><br><span style='font-size:10pt;'>Program by Jay Tanner</span></TD></TR>
<TR><TD ALIGN="center" BGCOLOR="LightCyan"><B>For Year</B>: <INPUT NAME="y" TYPE="text" VALUE="$y" SIZE="5" MAXLENGTH="5"><br><div style='line-height:125%; font-weight:bold;'>Valid From 1975 Onward</div>
</TD></TR>
<TR><TD ALIGN="center" BGCOLOR="white">
<INPUT style='font-size:120%;' TYPE="submit" NAME="ComputeButton" VALUE="C O M P U T E">
</TD></TR>
<tr><td>
<TABLE align='left' WIDTH="666" BORDER="0" ALIGN="bottom" BGCOLOR="black" CELLPADDING="8" CELLSPACING="4">
<TR><TD style='font-size:120%;' BGCOLOR="white" ALIGN="center" COLSPAN="2"><B>U.S.A. Daylight Saving Time Schedule For the Year $y</B><BR><BR><I>$DSTRuleUsed</I></TD></TR>
<TR>
<TD VALIGN="top" ALIGN = "center" BGCOLOR="LightYellow">$DSTStartsCalendar<BR></TD>
<TD VALIGN="top" ALIGN = "center" BGCOLOR="LightCyan">$DSTEndsCalendar<BR></TD>
</TR>
<TR>
<TD VALIGN="middle" COLSPAN="2" ALIGN="center" BGCOLOR="white"><B>$DurationStr</B><BR></TD>
</TR>
<TR>
<TD VALIGN="middle" COLSPAN="2" ALIGN="center" BGCOLOR="white">
<!--
<DIV ALIGN="justify">
Prior to the early 1980s, <i>Daylight Saving Time</i> across the U.S.A. was inconsistent, starting and ending on various dates in different states, sometimes arbitrarily, according to the whims of the current governors. So, when and where it was used, it was not used uniformly. These often variable inconsistencies caused some interstate as well as international commerce, recordkeeping, communications, travel-scheduling and other problems, so in 1986 a federal law was enacted to regulate its optional usage according to a consistent uniform schedule thereafter.
<BR><BR>
The new law mandated that the implementation of Daylight Saving Time was <i>optional</i>, but that all states <i>opting</i> to use Daylight Saving Time, do so <i>uniformly</i>, starting and ending on the same dates and those dates would be from the <i>first Sunday in April</i> to the <i>last Sunday in October</i>. This law applied to the period from 1986 to 2006. Under those rules, the duration of daylight saving time was sometimes 210 days (30 weeks) in some years and 203 days (29 weeks) in others.
<BR><BR>
<HR>
In 2007, an amended law extended the duration of Daylight Saving Time from the <I>second Sunday in March to the first Sunday in November</I>, starting two weeks earlier and ending two weeks later than before, adding four weeks or one more month of daylight saving time to the year than previously. This is the rule for Daylight Saving Time currently in use in the United States. Under this new rule, the duration of daylight saving time is always constant at 238 days (34 weeks).
<BR><BR>
<HR>
On the date when Daylight Saving Time starts, it begins at 2:00 AM local time in each time-zone, at which time, the clocks are set ahead exactly one hour so that, at that moment, it becomes 3:00 AM instead. The normally scheduled hour from 2:00 AM to 3:00 AM is skipped over or dropped so, in effect, one hour is lost from the clock that day and the next sunrise and sunset are suddenly one hour earlier than the day before. It gets daylight/dark one hour earlier than previously. Daylight saving time is now in effect.
<BR><BR>
On the date that Daylight Saving Time ends and we revert back to standard time, it begins at 2:00 AM local time in each time-zone, at which time the clocks are set back exactly one hour so that, at that moment, it becomes 1:00 AM - again. The hour from 1:00 AM to 2:00 AM is repeated. In effect, one extra hour is added to the clock that day and the next sunrise and sunset are suddenly one hour later than the day before. It gets daylight/dark one hour later than previously. Standard time is now back in effect.
<BR><BR>
With 2:00 AM being used as the transition time, there is never any confusion about the date after the transition either way since the date cannot change due to the transition.
<BR><BR>
--->
<!-- Yellow source code view link. --->
<table width="550" align="bottom" cellspacing="1" cellpadding="3">
<!-- Yellow source code view link. --->
<tr>
<td colspan="1" style="background:transparent; color:black; font-size:10pt;
text-align:center;">
<a href='View-Source-Code.php' target='_blank'
style='font-family:Verdana; color:black; background:yellow;
text-decoration:none; border:1px solid black; padding:4px;
border-radius:4px;'>
<span style='font-weight:normal;'>View/Copy PHP Source Code</span> </a>
</td>
</tr>
</table>
</TD>
</TR>
</TABLE></td></tr>
</TABLE>
<BR>
</FORM>
<BR>
</BODY>
</HTML>
_HTML;
// ************************************************************************
// ************************************************************************
function Final_Sunday ($y, $m, $CalMode=1)
{
$sign = ($y < 0)? -1 : 1;
$Y = $sign * $y;
$M = $m + 1;
$d = 1;
if ($M == 13) {$M=1; $Y = $Y+1;}
$ISOymdA = $sign * (($Y * 10000) + ($M * 100) + $d);
$JD12A = JD_For_ISOymd($ISOymdA, $CalMode) - 7;
$JD12B = $JD12A + (7 - ($JD12A + 1) % 7) % 7;
$ISOymdB = ISOymd_For_JD($JD12B, $CalMode);
return $ISOymdB;
} // End of Final_Sunday()
// THIS FUNCTION RETURNS THE SIMPLE JD NUMBER FOR ANY GIVEN CALENDAR DATE
// ON THE JULIAN AND GREGORIAN CALENDARS. THIS VALUE WILL ALWAYS EQUATE
// TO A POSITIVE INTEGER VALUE. TECHNICALLY, IT REFERS TO THE JD NUMBER
// FOR 12:00 NOON ON THE DATE. TO OBTAIN THE ASTRONOMICAL JD NUMBER FOR
// 00h ON THE DATE, SIMPLY SUBTRACT 0.5 FROM THIS VALUE.
function JD_For_ISOymd ($ISOymd, $CalMode=1)
{
// ----------------------------------------------
// EXTRACT INDIVIDUAL DATE ARGUMENTS (y,m,d) FROM
// WITHIN INTEGER ENCODED DATE ARGUMENT (ymd).
$u = abs($ISOymd);
$w = floor($u / 10000);
$y = (($ISOymd < 0) ? -1 : 1) * $w;
$m = floor(($u - 10000*$w) / 100);
$d = ($u - 10000*$w - 100*$m);
$a = floor((14-$m) / 12);
$b = (($y < 0) ? $y+1 : $y) - $a;
$c = floor($b/100);
// --------------------------------------
// COMPUTE SIMPLE JD FOR DATE (AT 12:00).
// THIS VALUE WILL ALWAYS EQUATE TO A
// POSITIVE INTEGER VALUE.
$JD = floor(30.6001*(12*$a + $m + 1))
+ floor(365.25*($b + 4716)) - 1524 + $d
+ $CalMode*(floor($c/4) - $c + 2);
return $JD;
} // End of JD_For_ISOymd()
// ************************************************************************
// ************************************************************************
// THIS FUNCTION SERVES AS AN INVERSE JD FUNCTION. GIVEN ANY GENERAL JD
// NUMBER AND CALENDAR MODE, IT RETURNS THE CORRESPONDING SIGNED INTEGER
// ENCODED DATE (ymd). THE GENERAL JD VALUE IS NOT RESTRICTED TO INTEGER
// VALUES ONLY. ANY FRACTIONAL PART CORRESPONDING TO THE TIME OF DAY IS
// IGNORED, SINCE ONLY THE DATE ON THE CALENDAR APPLIES HERE.
function ISOymd_For_JD ($JD, $CalMode=1)
{
// --------------------------------
// COMPUTE JD12 VALUE FOR DATE FROM
// THE GENERAL JD INPUT ARGUMENT.
$JD12 = floor($JD + 0.5);
// --------------------------
// ACCOUNT FOR CALENDAR MODE.
$e = $CalMode * floor(($JD12 - 1867216.25) / 36524.25);
$f = $JD12 + $CalMode * ($e - floor($e/4) + 1);
// -------------------------
// AUXILIARY WORK VARIABLES.
$g = $f + 1524;
$h = floor(($g - 122.1) / 365.25);
$i = floor(365.25 * $h);
$j = floor(($g - $i) / 30.6001);
// -----------------------------------
// COMPUTE THE CALENDAR DATE ELEMENTS.
$d = $g - $i - floor(30.6001 * $j);
$m = $j - 12*floor($j/14) - 1;
$w = $h - 4716 + floor((14-$m) / 12);
// -----------------------------------------
// ADJUST FOR CALENDAR YEAR CONVENTION USED,
// WHERE: NEG YEAR = BC YEAR
$y = ($w < 1) ? $w-1 : $w;
// ------------------------------------------------------
// CONSTRUCT INTEGER ENCODED DATE CONTAINING THE CALENDAR
// DATE ELEMENTS IN A SINGLE � INTEGER VALUE.
$ISOymd = (($y < 0) ? -1 : 1) * (10000*abs($y) + 100*$m + $d);
return $ISOymd;
} // End of ISOymd_For_JD()
// ************************************************************************
// ************************************************************************
/*
THIS FUNCTION RETURNS A CALENDAR IN THE FORM OF AN HTML
TABLE FOR THE MONTH CONTAINING THE GIVEN DATE .
THIS FUNCTION IS ALSO VALID FOR PROLEPTIC DATES.
$y = YEAR NUMBER ARGUMENT (1 to 32767)
$m = MONTH NUMBER ARGUMENT (1 to 12)
$JD1 = JD NUMBER OF 1st DAY OF MONTH
$HDay = DATE TO HIGHLIGHT WITHIN CALENDAR (0 = NONE)
$MName = NAME OF GIVEN MONTH
$DoW1 = DAY OF WEEK CODE (0 to 6) FOR 1st OF MONTH
$MDays = NUMBER OF DAYS IN GIVEN MONTH
THE OPTIONAL PARAMETER $HDay IS THE DAY OF THE MONTH TO
BE HIGHLIGHTED IN THE CALENDAR DISPLAY. IF ($HDay == 0),
THEN NO DATE WILL BE HIGHLIGHTED.
*/
Function Calendar_Table ($ISOymd, $CalMode, $TitleColor, $SpecialFlag=FALSE)
{
// ---------------------------------------------
// EXTRACT INDIVIDUAL DATE ELEMENTS (y,m,d) FROM
// WITHIN INTEGER ENCODED DATE ARGUMENT (ymd).
$w = floor(abs($ISOymd) / 10000);
$y = (($ISOymd < 0) ? -1 : 1) * $w;
$m = floor((abs($ISOymd) - 10000*$w) / 100);
$d = (abs($ISOymd) - 10000*$w - 100*$m);
// ----------------------------------------------
// GET PARAMETERS NEEDED TO CREATE CALENDAR TABLE
//
// IF ($d == 0), THEN NO DATE WILL BE HIGHLIGHTED
$HDay = $d;
$ISOymd1 = "$y" . sprintf("%02d", $m) . "01";
$JD1 = JD_For_ISOymd ($ISOymd1, $CalMode);
$MName = Month_String ($m);
$DoW1 = ($JD1 + 1) % 7;
$MDays = Days_In_Month ($y, $m, $CalMode);
$era = ($y < 0) ? "BC" : "AD";
if ($y > 0 && $y > 1000) {$era = " ";}
$yEra = abs($y) . " $era";
$CMode = ($CalMode == 0) ? "J" : "G";
if ($y == 1582 && $m == 10 && $SpecialFlag == TRUE)
{
return JG_Transition_Calendar_Table();
}
// ---------------------------------
// BEGIN CALENDAR TABLE CONSTRUCTION
$CalTable =
"<TABLE BGCOLOR='black' CELLPADDING='2' CELLSPACING='1'>\n
<TR BGCOLOR=\"$TitleColor\"><TD COLSPAN='7' ALIGN='center'><B>$CMode $yEra $MName</B></TD></TR>\n
<TR BGCOLOR='Light$TitleColor'><TD WIDTH='36' ALIGN='center'>Sun</TD><TD WIDTH='36' ALIGN='center'>Mon</TD><TD WIDTH='36' ALIGN='center'>Tue</TD><TD WIDTH='36' ALIGN='center'>Wed</TD><TD WIDTH='36' ALIGN='center'>Thu</TD><TD WIDTH='36' ALIGN='center'>Fri</TD><TD WIDTH='36' ALIGN='center'>Sat</TD></TR>\n<TR>\n";
// ---------------------------------------------
// FILL ANY BLANK CELLS AT BEGINNING OF CALENDAR
// MATRIX IF MONTH DOES NOT START ON A SUNDAY.
for ($i=1; $i <= $DoW1; $i++)
{$CalTable .= "<TD BGCOLOR='white'> </TD>\n";}
// ----------------------------------
// FILL IN CALENDAR DAY NUMBER CELLS.
for ($day=1; $day <= $MDays; $day++)
{
// PATCH TO CHANGE TITLE COLOR TO GreenYellow FOR OCTOBER OF 1582
if ($y == 1582 && $m == 10) {$TitleColor = "GreenYellow";}
$BgC = ($day != $HDay)? "white" : "$TitleColor";
if ($BgC == "$TitleColor")
{$Bold1 = "<B>"; $Bold2 = "</B>";}
else
{$Bold1 = $Bold2 = "";}
$CalTable .= "<TD BGCOLOR=\"$BgC\" ALIGN='center'>$Bold1$day$Bold2";
if (($day + $DoW1 ) % 7 == 0)
{$CalTable .= "</TD>\n</TR>\n<TR>\n";}
else
{$CalTable .= "</TD>\n";}
}
// ----------------------------------------------
// FILL ANY BLANK CELLS AT END OF CALENDAR MATRIX
// IF MONTH DOES NOT END ON A SATURDAY.
$DoW = ($JD1 + $MDays) % 7;
$DoWEnd = ($DoW + ($MDays - $d) % 7) % 7;
for ($i=0; $i < 6-$DoW; $i++)
{$CalTable .= "<TD BGCOLOR='white'> </TD>\n";}
// --------------------
// CLOSE OUT THE TABLE.
$CalTable .= "</TR>\n</TABLE>\n";
// ------------------------------------------
// PATCH TO DELETE REDUNDANT EMPTY TABLE ROW.
$CalTable = Str_Replace("<TR>\n</TR>", "", $CalTable);
// -----
// DONE.
return $CalTable;
} // End of Calendar_Table()
// ************************************************************************
// ************************************************************************
// CALENDAR TABLE FOR ANY YEAR
// JULIAN = YELLOW
// GREGORIAN = CYAN
function Calendar_For_Year_Table ($y, $CalMode=1)
{
$out = "";
// -----------------
// GET CALENDAR MODE
$CalModeStr = (($CalMode == 0) ? "Jul" : "Gregor") . "ian";
$era = ($y < 0) ? " BC" : " AD";
if ($y > 1000) {$era = "";}
$yEra = abs($y) . $era;
$HMonth = date("m");
// SET CALENDAR COLOR
$CalColor = ($CalMode == 0)? "Yellow" : "Cyan";
// -----------------------------
// DEFINE TITLE ROW FOR CALENDAR
$out = "<TR><TD COLSPAN='3' ALIGN='center' VALIGN='top' BGCOLOR='white'><B>Calendar For $CalModeStr Year $yEra<BR><BR></B></TD></TR>\n";
$w = "";
// -------------------------------------------------------
// CONSTRUCT 3 COLUMNS by 4 ROWS CALENDAR MATRIX FOR YEAR.
// m = 3*row + column + 1
for ($row=0; $row < 4; $row++)
{
for ($column=0; $column < 3; $column++)
{
if ($HMonth == 3*$row + $column + 1) {$HDay = date("d");} else {$HDay = "00";}
$ISOymd = "$y" . sprintf("%02d", 3*$row + $column + 1) . $HDay;
$out .= "<TD VALIGN='top'>" . Calendar_Table ($ISOymd, $CalMode, "$CalColor") . "</TD>\n";
}
$out = "<TR>" . $out . "</TR>\n";
}
// -------------------------------------------
// FINISH UP AND CLOSE OUT THE TABLE STRUCTURE
return "<TABLE BGCOLOR='black'>$out</TABLE>\n";
}
// ************************************************************************
// ************************************************************************
// THIS FUNCTION RETURNS THE FULL MONTH NAME STRING
// CORRESPONDING TO A GIVEN MONTH NUMBER (1 to 12).
function Month_String ($m)
{
// -------------------------
// DEFINE MONTH NAMES TABLE.
$months = "January February March April May June July August SeptemberOctober November December ";
// ------------------------------------------------
// IF MONTH NUMBER (m) IS WITHIN THE RANGE 1 TO 12,
// THEN RETURN THE MONTH NAME STRING, OTHERWISE
// RETURN AN EMPTY STRING TO INDICATE AN ERROR.
if (intval($m) > 0 and intval($m) < 13)
{return trim(substr($months, 9*($m-1), 9));}
else
{return "";}
} // End of Month_String()
// ************************************************************************
// ************************************************************************
function Days_In_Month ($y, $m, $CalMode=1)
{
// Account for BC or AD year as indicated.
// if ($y > 0) {$w = $y;} else {$w = $y+1;}
$w = ($y > 0) ? $y : $y+1;
// Determine if year is a leap year according to the Julian
// calendar and set the leap year flag accordingly.
// if ($w % 4 == 0) {$leap = 1;} else {$leap = 0;}
$leap = ($w % 4 == 0) ? 1 : 0;
// If the calendar mode is Gregorian, then apply the new
// leap year rule and set the leap year flag accordingly.
if ($CalMode == 1 && $w % 100 == 0)
{
// if ($w % 400 == 0) {$leap = 1;} else {$leap = 0;}
$leap = ($w % 400 == 0) ? 1 : 0;
}
// Compute the number of days in the given month.
$u = floor(($m-1) / 7);
$w = $m % 2;
$days = 30 + $w - 2*($m == 2) + ($m == 2 && $leap == 1) - 2*$u*$w + $u;
// Done.
return $days;
} // End of Days_In_Month()
// ************************************************************************
// ************************************************************************
// THIS FUNCTION RETURNS THE ymd OF THE nth DoW OF A GIVEN y, m
//
// IT IS USED TO FIND SUCH THINGS AS THE 4th THURSDAY OR 3rd MONDAY,
// ETC., OF ANY MONTH OF ANY GIVEN YEAR.
function nth_DoW_In_ym ($n, $DoW, $y, $m, $CalMode=1)
{
// ------------------------------------------------
// CONSTRUCT INTEGER ENCODED DATE VALUE FOR 1st DAY
// OF MONTH (m) OF YEAR (y).
$ym01 = (($y < 0) ? -1 : 1)*(10000*abs($y) + 100*$m + 1);
// ---------------------------------------
// COMPUTE JD NUMBER FOR 1st DAY OF MONTH.
$JD1 = JD_For_ISOymd ($ym01, $CalMode);
// ---------------------------------
// COMPUTE DoW FOR 1st DAY OF MONTH.
$DoW1 = ($JD1 + 1) % 7;
// ------------------------------
// COMPUTE OFFSET FROM 1st DAY OF
// MONTH TO 1st DoW IN MONTH.
$w = $DoW - $DoW1;
$offset = $w + (($w < 0) ? 7 : 0);
// --------------------------------------
// COMPUTE JD NUMBER OF Nth DoW OF MONTH.
$JD = $JD1 + $offset + 7*($n-1);
// ---------------------------------------
// CALL THE INVERSE JD FUNCTION TO COMPUTE
// THE DATE CORRESPONDING TO THE JD.
$ymd = ISOymd_for_jd ($JD, $CalMode);
return $ymd;
}
// ************************************************************************
// ************************************************************************
/*
This function computes the integer-encoded date of the
last DoW of any given month and year on the Gregorian
or Julian calendar (Gregorian = Default).
For example, to find the last Friday (DoW = 5) in October
of 1934 on the Gregorian calendar:
$ymd = Last_DoW_in_yyyymn (5, 193410);
To find the last Sunday (DoW = 0) in February of 1369 on
the old-style Julian calendar
$ymd = Last_DoW_in_yyyymn (0, 136902, 'J');
*/
function Last_DoW_in_yyyymn ($DoW, $yyyymn, $CalMode='G')
{
$yyyy = intval(substr(trim($yyyymn), 0,4));
$mn = substr(trim($yyyymn), 4,2);
$dow = intval(trim($DoW));
$c = strtoupper(substr(trim($CalMode), 0,1));
// Get date of 1st occurence of DoW in following month.
$m = intval($mn) + 1;
if ($m == 13) {$m = 1; $yyyy += 1;}
$mn = sprintf("%02d", $m);
$yyyymndd = trim(Nth_DoW_in_yyyymn(1, $dow, "$yyyy$mn", $c));
$yyyy = intval(substr(trim($yyyymndd), 0,4));
$mn = substr(trim($yyyymndd), 4,2);
$dd = substr(trim($yyyymndd), 6,2);
$m = intval($mn);
$d = intval($dd);
if ($c == 'J')
{
list($m, $d, $y) =
preg_split("[/]", JDtoJulian(JulianToJD($m, $d, $yyyy) - 7));
$yyyymndd = 10000*$y + 100*$m + $d;
}
else
{
list($m, $d, $y) =
preg_split("[/]", JDtoGregorian(GregorianToJD($m, $d, $yyyy) - 7));
$yyyymndd = 10000*$y + 100*$m + $d;
}
return $yyyymndd;
} // End of Last_DoW_in_yyyymn (...)
function Nth_DoW_in_yyyymn ($N, $DoW, $yyyymn, $CalMode="G")
{
$y = intval(substr($yyyymn,0,4));
$m = intval(substr($yyyymn,4,2));
if (strtoupper(substr($CalMode,0,1)) == "J")
{
$CalMode = "Julian";
$JDNum = JulianToJD($m, 1, $y);
$dDoW = $DoW - ($JDNum + 1) % 7;
$JDNum = $JDNum + (($dDoW < 0)? $dDoW + 7 : $dDoW) + 7*($N-1);
$DateStr = JDtoJulian($JDNum);
}
else
{
$CalMode = "Gregorian";
$JDNum = GregorianToJD($m, 1, $y);
$dDoW = $DoW - ($JDNum + 1) % 7;
$JDNum = $JDNum + (($dDoW < 0)? $dDoW + 7 : $dDoW) + 7*($N-1);
$DateStr = JDtoGregorian($JDNum);
}
list($m, $d, $y) = preg_split("[/]", $DateStr);
$yyyymndd = 10000*$y + 100*$m + $d;
return "$yyyymndd";
} // End of Nth_DoW_in_yyyymn (...)
?>