<?php
/*
---------------------------------------------------------------------
E.U. Summer Time Calculator
This program computes the E.U. Summer Time
schedule for any year from 2002 onward.
Author:
Jay Tanner - 2023
Development Language:
PHP v7.4.9
License: Public Domain
---------------------------------------------------------------------
E.U. SUMMER TIME CORRESPONDS TO DAYLIGHT SAVING TIME IN THE
U.S.A., BUT IT DOES NOT START AND END ON THE SAME DATES AS
U.S. DAYLIGHT SAVING TIME.
THE E.U. RULE FOR SUMMER TIME IS:
IT STARTS ON THE LAST SUNDAY IN MARCH AND ENDS ON THE LAST
SUNDAY IN OCTOBER.
CLOCKS IN ALL TIME ZONES CHANGE SIMULTANEOUSLY AT 01:00 UTC
*/
// Initialize cookies
ob_start();
$_PROGRAM_VERSION_ = '';
$DiffDays = "0";
$DurationStr = "";
$_COOKIE_NAME_ = "EU_Summer_Time_Schedule_Calculator";
$cYear = gmdate("Y");
$_ACTION_FILE_NAME_ = $_SERVER['SCRIPT_NAME'];
$_HTML_TITLE_ = "E.U. Summer Time Schedule Calculator";
$_HEADER_ = "E.U. Summer Time Schedule Calculator";
// ===========================================================
// Set cookie expiration date 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.
$ToExpire = 30 * 86400;
$DLLink = '';
if (substr(Filter_Input(INPUT_SERVER, 'SCRIPT_FILENAME'), 0,3) <> 'D:/')
{
$DLLink = "<a href='eu-summer-time-schedule-calculator.zip'>Download PHP 7 Source Code For This Program</a>";
}
// =======================================
// Do this if "Submit" button was clicked.
if (IsSet($_POST["Submit"]))
{
$y = Filter_Input(INPUT_POST, 'y');
if ($y == '') {$y = date('Y');}
$CookieDataString = "$y";
setcookie ($_COOKIE_NAME_, $CookieDataString, time() + $ToExpire);
}
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() + $ToExpire);
}
}
// **********************************
// **********************************
// AT THIS POINT, THE INPUT INTERFACE
// VALUES SHOULD BE READY FOR USE
// ---------------------------------------
// CHECK FOR AND BLOCK INVALID YEAR INPUT.
if ($y < 2002 or $y > 9999)
{
$EUSTStartsCalendar = "<b style='font-size:150%;'>Invalid year.</b>";
$EUSTEndsCalendar = "<b style='font-size:150%;'>Year must be 2002 or later.<b>";
$EUSTRuleUsed = "<B style='color:red; font-size:150%;'>ERROR</B>";
}
else
// =============================
// CONTINUE BELOW IF YEAR IS OK.
// MAIN COMPUTATIONS START HERE
{
$EUSTRuleUsed = "Starts on last Sunday in March at 01:00 UTC - Set ahead 1 hour<br><br>Ends on last Sunday in October at 01:00 UTC - Set back 1 hour<br><br>";
$ISOymd = Final_Sunday ($y, 3, 1);
$JDA = JD_For_ISOymd ($ISOymd);
$EUSTStartsCalendar = "<B>E.U. Summer Time Start Date UTC</B><BR><BR>\n" . Calendar_Table ($ISOymd, 1, "Yellow");
$EUSTStartsCalendar = str_replace("G ", "", $EUSTStartsCalendar);
$ISOymd = Final_Sunday ($y, 10, 1);
$JDB = JD_For_ISOymd ($ISOymd);
$EUSTEndsCalendar = "<B>E.U. Summer Time End Date UTC</B><BR><BR>\n" . Calendar_Table ($ISOymd, 1, "Cyan");
$EUSTEndsCalendar = str_replace("G ", "", $EUSTEndsCalendar);
$DiffDays = $JDB - $JDA;
$DurationWeeks = $DiffDays / 7;
$DurationStr = "Duration = $DiffDays days = $DurationWeeks weeks";
// =====================================
// CONSTRUCT FORMATTED TEXT OUTPUT BLOCK
$out = " y = $y\n";
}
// ===========================================
// DYNAMIC HTML DOCUMENT OUTPUT FOLLOWS BELOW.
print <<< _HTML
<!DOCTYPE HTML>
<HTML>
<head>
<TITLE>E.U. Summer Time Schedule Calculator</TITLE>
<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='EU Summer 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="$_ACTION_FILE_NAME_">
<TABLE align='left' WIDTH="666" BORDER="0" 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;'>E.U. Summer Time Schedule Calculator</B></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 2002 Onward</div>
</TD></TR>
<TR><TD ALIGN="center" BGCOLOR="white">
<INPUT style='font-size:120%;' TYPE="submit" NAME="Submit" VALUE="C O M P U T E">
</TD></TR>
<tr><td>
<TABLE align='center' WIDTH="666" BORDER="0" BGCOLOR="black" CELLPADDING="8" CELLSPACING="4">
<TR><TD style='font-size:120%; padding:8px;' BGCOLOR="white" ALIGN="center" COLSPAN="2" ><B>E.U. (European Union) Summer Time Schedule for the Year $y</B><BR><BR><I>$EUSTRuleUsed</I></TD></TR>
<TR>
<TD VALIGN="top" ALIGN = "center" BGCOLOR="LightYellow">$EUSTStartsCalendar<BR></TD>
<TD VALIGN="top" ALIGN = "center" BGCOLOR="LightCyan">$EUSTEndsCalendar<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" BGCOLOR="white">
<!-- Yellow source code view link. --->
<table width="666" 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>
<div style='font-size:80%; text-align:center;'>
PHP Program by Jay Tanner - $cYear
<br><br>
</div>
</TD>
</TR>
</TABLE>
</td></tr>
</TABLE>
<BR>
</FORM>
<BR><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 ($ymd, $CalMode, $TitleColor, $SpecialFlag=FALSE)
{
// ---------------------------------------------
// EXTRACT INDIVIDUAL DATE ELEMENTS (y,m,d) FROM
// WITHIN INTEGER ENCODED DATE ARGUMENT (ymd).
$w = floor(abs($ymd) / 10000);
$y = (($ymd < 0) ? -1 : 1) * $w;
$m = floor((abs($ymd) - 10000*$w) / 100);
$d = (abs($ymd) - 10000*$w - 100*$m);
// ----------------------------------------------
// GET PARAMETERS NEEDED TO CREATE CALENDAR TABLE
//
// IF ($d == 0), THEN NO DATE WILL BE HIGHLIGHTED
$HDay = $d;
$ymd1 = "$y" . sprintf("%02d", $m) . "01";
$JD1 = JD_for_ISOymd ($ymd1, $CalMode);
$MName = Month_Str ($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";}
$ymd = "$y" . sprintf("%02d", 3*$row + $column + 1) . $HDay;
$out .= "<TD VALIGN='top'>" . Calendar_Table ($ymd, $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_Str ($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 ($m > 0 && $m < 13)
{return trim(substr($months, 9*($m-1), 9));}
else
{return "";}
} // End of Month_Str()
// ************************************************************************
// ************************************************************************
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()
// ************************************************************************
// ************************************************************************
?>