The following is actually a couple of Class Snippets and a little CSS:
namespace Library\Calendar;
use DateTime;
use Library\Database\Database;
use Library\Holiday\Holiday;
class Calendar {
protected $date = \NULL;
protected $page = 0;
public $output = \NULL;
protected $username = \NULL;
protected $user_id = \NULL;
protected $query = \NULL;
protected $stmt = \NULL;
protected $urlDate = \NULL;
protected $sendDate = \NULL;
protected $prev = \NULL;
public $current = \NULL;
protected $next = \NULL;
protected $month = \NULL;
protected $day = \NULL;
protected $year = \NULL;
protected $days = \NULL;
protected $currentDay = \NULL;
protected $highlightToday = \NULL;
protected $highlightHoliday = \NULL;
protected $isHoliday = \NULL;
protected $prevMonth = \NULL;
protected $nextMonth = \NULL;
public $selectedMonth = \NULL;
public $n = \NULL;
public $z = 0;
public $result = \NULL;
public $tab = "\t"; // Tab 2 spaces over;
public $calendar = []; // The HTML Calender:
protected $holiday = [];
protected $alphaDay = [0 => "Sun", 1 => "Mon", 2 => "Tue", 3 => "Wed", 4 => "Thu", 5 => "Fri", 6 => "Sat"];
protected $smallDays = [0 => "S", 1 => "M", 2 => "T", 3 => "W", 4 => "T", 5 => "F", 6 => "S"];
protected $imporantDates = [];
protected $myPage = \NULL;
protected $now = \NULL;
protected $monthlyChange = \NULL;
protected $pageName = "index";
/* Constructor to create the calendar */
public function __construct($date = null) {
$this->selectedMonth = new \DateTime($date, new \DateTimeZone("America/Detroit"));
$this->current = new \DateTime($date, new \DateTimeZone("America/Detroit"));
$this->current->modify("first day of this month");
$this->n = $this->current->format("n"); // Current Month as a number (1-12):
}
public function set_user_id($user_id = -1) {
$this->user_id = $user_id;
}
public function checkIsAValidDate($myDateString) {
return (bool) strtotime($myDateString);
}
public function phpDate() {
$setDate = filter_input(INPUT_GET, 'location', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$valid = $this->checkIsAValidDate($setDate);
if (isset($setDate) && strlen($setDate) === 10 && $valid) {
self::__construct($setDate);
}
}
public function returnDate() {
return $this->selectedMonth;
}
public function getHolidayNames() {
return $this->isHoliday->checkForHoliday($this->selectedMonth->format('Y-m-j'));
}
/*
* Not Currently Being Used:
*/
protected function checkForEntry($calDate) {
$blog = "blog.php";
$db = Database::getInstance();
$pdo = $db->getConnection();
$this->username = isset($_SESSION['user']) ? $_SESSION['user']->username : \NULL;
$this->query = 'SELECT 1 FROM cms WHERE page_name=:page_name AND DATE_FORMAT(date_added, "%Y-%m-%d")=:date_added AND user_id=:user_id';
$this->stmt = $pdo->prepare($this->query);
$this->stmt->execute([':page_name' => $blog, ':date_added' => $calDate, ':user_id' => $this->user_id]);
$this->result = $this->stmt->fetch();
/* If result is true there is data in day, otherwise no data */
if ($this->result) {
return \TRUE;
} else {
return \FALSE;
}
}
protected function isItToday() {
/*
* If selected month (user) equals today's date then highlight the day, if
* not then treat it as a normal day to be displayed.
*/
if ($this->now->format("F j, Y") === $this->current->format("F j, Y")) {
$this->calendar[$this->z]['class'] = 'item today';
$this->calendar[$this->z]['date'] = $this->current->format("j");
} else {
$this->todaysSquares(); // Regular Reg. Boxes - Lt. Green Holidays
}
}
protected function todaysSquares() {
/*
* Determine if just a regular day or if it's a holiday.
*/
if (array_key_exists($this->current->format("Y-m-d"), $this->holiday[0])) {
$this->calendar[$this->z]['class'] = 'item holiday';
$this->calendar[$this->z]['date'] = $this->current->format("j");
} else {
$this->calendar[$this->z]['class'] = 'item date';
$this->calendar[$this->z]['date'] = $this->current->format("j");
}
}
protected function drawDays() {
$this->now = new \DateTime("Now", new \DateTimeZone("America/Detroit"));
//echo "<pre>" . print_r($this->holiday, 1) . "</pre>";
$x = 1;
while ($x <= 7) {
/*
* Determine if selected month (user) equal current month to be
* displayed. If it is proceed with check, if not the fade the box,
* so that the user will know that it is not the month currently being
* displayed.
*/
if ($this->selectedMonth->format('n') === $this->current->format('n')) {
$this->isItToday();
} else {
/*
* Fade out previous and next month's dates
*/
$this->calendar[$this->z]['class'] = 'item prev-date';
$this->calendar[$this->z]['date'] = $this->current->format("j");
}
$this->current->modify("+1 day");
$x += 1;
$this->z += 1;
}
}
protected function controls() {
$this->monthlyChange = new DateTime($this->current->format("F j, Y"));
$this->monthlyChange->modify("-1 month");
$this->prev = $this->monthlyChange->format("Y-m-d");
$this->monthlyChange->modify("+2 month");
$this->next = $this->monthlyChange->format("Y-m-d");
/* Create heading for the calendar */
$this->calendar[$this->z]['previous'] = $this->pageName . '?location=' . $this->prev;
$this->calendar[$this->z]['next'] = $this->pageName . '?location=' . $this->next;
}
protected function display($pageName) {
$holidayCheck = new Holiday($this->current->format("F j, Y"), 1);
$this->holiday[] = $holidayCheck->holidays();
$this->pageName = $pageName;
$this->controls();
$this->calendar[$this->z]['month'] = $this->current->format('F Y');
/* Generate last Sunday of previous Month */
$this->current->modify("last sun of previous month");
/*
* Output 6 rows (42 days) guarantees an even calendar that will
* display nicely.
*/
$num = 1;
while ($num <= 6) {
$this->drawDays();
$num += 1;
}
return $this->calendar;
}
public function generateCalendar(string $pageName = "index") {
return $this->display($pageName);
}
}
The below class just figures out the Main Holidays:
<?php
namespace Library\Holiday;
use DateTime;
class Holiday {
private $month = \NULL;
private $year = \NULL;
private $dateFormat = \NULL;
private $tempDate = \NULL;
private $numOfYears = \NULL;
private $easter = \NULL;
public $holidays = []; // array of holidays:
public function __construct($date = null, $numOfYrs = 1) {
$this->dateFormat = new DateTime($date, new \DateTimeZone("America/Detroit"));
$this->year = $this->dateFormat->format("Y");
$this->month = $this->dateFormat->format("F");
$this->numOfYears = $numOfYrs;
}
public function setConstructor($date = \NULL, $numOfYears = 1) {
self::__construct($date, $numOfYears);
}
private function convertToDisplayDate($tempDate = \NULL) {
$this->dateFormat = new DateTime($tempDate, new \DateTimeZone("America/Detroit"));
return $this->tempDate = $this->dateFormat->format("F j, Y");
}
public function holidays() {
$this->holidays[$this->year . "-01-01"] = "New Year's Day";
if ($this->year > 1969 && $this->year < 2038) {
$this->easter = new DateTime('@' . easter_date($this->year), new \DateTimeZone("America/Detroit"));
$this->holidays[$this->easter->format("Y-m-d")]['easter'] = "Easter Sunday";
}
$this->holidays[\date("Y-m-d", \strtotime("Last Monday of May " . $this->year))] = "Memorial Day";
$this->holidays[$this->year . "-07-04"] = "4th of July";
$this->holidays[\date("Y-m-d", \strtotime("First Monday of September " . $this->year))] = "Labor Day";
$this->holidays[\date("Y-m-d", \strtotime("Fourth Thursday of November" . $this->year))] = "Thanksgiving Day";
$this->holidays[$this->year . '-12-25'] = "Christmas Day";
return $this->holidays;
}
}
The Below is just CSS (using SASS) to stylize the Calendar
.calendar-container {
background-color: #E6E6FA;
border: 0.125em solid #E6E6FA;
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: repeat (8, 1fr);
grid-auto-flow: dense;
grid-gap: 0.188em 0.125em; // 2px = 0.125em 3px = 0.188en
width: 18.75em; // 400px = 25.000em 300px = 18.750
margin: 0 auto; // 10px = 0.625em
}
.item {
text-align: center;
}
.previous, .next {
grid-column: 1 / span 1;
grid-row: 1;
line-height: 2.500em;
margin-top: 0.625em;
.prev-left, .next-right {
font-size: 1.4em;
text-decoration: none;
color: #2e2e2e;
&:hover {
color: green;
}
}
}
.next {
grid-column: 7 / span 1;
}
.cal-date {
grid-column: 2 / span 5;
padding: 0.438em; // 7px = 0.438em
grid-row: 1;
line-height: 2.500em;
}
[class^="day"] {
font-family: 'Titillium Web', Arial, sans-serif;
background-color: #2e2e2e;
text-align: center;
color: #fff;
text-transform: capitalize;
padding: 0.188em; // 5px = 0.313em
}
.prev-date {
background-color: #fff;
color: #E6E6FA;
padding: 0.625em;
}
.date {
background-color: #fff;
color: #2e2e2e;
padding: 0.625em;
}
.calendar-container h1 {
font-size: 1.4em;
color: #2e2e2e;
}
.calendar-container p {
font-family: 'Titillium Web', Arial, sans-serif;
font-size: 0.8em;
}
.today, .holiday {
background-color: darken( #E6E6FA, 10% );
color: #fff;
font-weight: bolder;
padding: 0.625em;
}
.holiday {
background-color: rgba(green, 0.6);
}
/* END OF CALENDAR CSS */
You can see it in action here : https://www.miniaturephotographer.com/blog.php