<?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_$CookieDataStringtime() + $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_$CookieDataStringtime() + $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 ($y31);
       
$JDA JD_For_ISOymd ($ISOymd);
       
$EUSTStartsCalendar "<B>E.U. Summer Time Start Date UTC</B><BR><BR>\n" Calendar_Table ($ISOymd1"Yellow");
       
$EUSTStartsCalendar str_replace("G&nbsp;"""$EUSTStartsCalendar);
       
$ISOymd Final_Sunday ($y101);
       
$JDB JD_For_ISOymd ($ISOymd);
       
$EUSTEndsCalendar "<B>E.U. Summer Time End Date UTC</B><BR><BR>\n" Calendar_Table ($ISOymd1"Cyan");
       
$EUSTEndsCalendar str_replace("G&nbsp;"""$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>:&nbsp; <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;'>
         &nbsp;<span style='font-weight:normal;'>View/Copy PHP Source Code</span>&nbsp;</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;
   
$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 + (- ($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) * $w;
   
$m floor(($u 10000*$w) / 100);
   
$d = ($u 10000*$w 100*$m);

   
$a floor((14-$m) / 12);
   
$b = (($y 0) ? $y+$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-$w;

// ------------------------------------------------------
// CONSTRUCT INTEGER ENCODED DATE CONTAINING THE CALENDAR
// DATE ELEMENTS IN A SINGLE � INTEGER VALUE.

   
$ISOymd = (($y 0) ? -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) * $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  "$ysprintf("%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 && $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&nbsp;$yEra&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$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'>&nbsp;</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 ) % == 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'>&nbsp;</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  "$ysprintf("%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 && $m 13)

      {return 
trim(substr($months9*($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 == 0) ? 0;

// If the calendar mode is Gregorian, then apply the new
// leap year rule and set the leap year flag accordingly.
   
if ($CalMode == && $w 100 == 0)
      {
   
//    if ($w % 400 == 0)  {$leap = 1;} else {$leap = 0;}
       
$leap = ($w 400 == 0) ? 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 == && $leap == 1) - 2*$u*$w $u;

// Done.
   
return $days;

// End of  Days_In_Month()


// ************************************************************************
// ************************************************************************









?>