0 Replies - 1664 Views - Last Post: 18 October 2014 - 07:44 AM

#1 goku87  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 4
  • View blog
  • Posts: 81
  • Joined: 17-October 09

Doomsday Calendar (Unix Independent)

Posted 18 October 2014 - 07:44 AM

This is a re-post from a class I had posted back in 2012. The question posed was if there was a means for getting dates without using the Unix timekeeping method (seconds since epoch), which can be prone to the 2038 problem for 32-bit systems. Although the issue will be unlikely in the future, I still wanted to know if there was a way to get dates for days without using it, thus enter the doomsday rule. This algorithm provides a method for calculating the day of week for any given date. By using this method, I found it possible to make complete calendars. Enjoy!

<?php
class doomsdayCalendar {
	/*
	 ______                                             __                  
	|_   _ `.                                          |  ]                 
	  | | `. \  .--.    .--.   _ .--..--.   .--.   .--.| |  ,--.    _   __  
	  | |  | |/ .'`\ \/ .'`\ \[ `.-. .-. | ( (`\]/ /'`\' | `'_\ :  [ \ [  ] 
	 _| |_.' /| \__. || \__. | | | | | | |  `'.'.| \__/  | // | |,  \ '/ /  
	|______.'  '.__.'  '.__.' [___||__||__][\__) )'.__.;__]\'-;__/[\_:  /   
	   ______         __                       __                  \__.'    
	 .' ___  |       [  |                     |  ]                          
	/ .'   \_| ,--.   | | .---.  _ .--.   .--.| |  ,--.   _ .--.            
	| |       `'_\ :  | |/ /__\\[ `.-. |/ /'`\' | `'_\ : [ `/'`\]           
	\ `.___.'\// | |, | || \__., | | | || \__/  | // | |, | |               
	 `.____ .'\'-;__/[___]'.__.'[___||__]'.__.;__]\'-;__/[___]
	
	|----------------------------------------------------------------|
			 _    _____  __        ___    __   _____  ____             
			| | |  | |  / /`      | | \  / /\   | |  | |_              
			\_\_/  |_|  \_\_,     |_|_/ /_/--\  |_|  |_|__             
	 _   _      ___   ____  ___   ____  _      ___   ____  _     _____ 
	| | | |\ | | | \ | |_  | |_) | |_  | |\ | | | \ | |_  | |\ |  | |  
	|_| |_| \| |_|_/ |_|__ |_|   |_|__ |_| \| |_|_/ |_|__ |_| \|  |_|  	

	[ PURPOSE / ABOUT ]
		Designed to be independent from the Unix time-keeping method, the doomsdayCalendar class
		utilizes doomsdays to create calendars of any year. This started as a proof-of-concept
		idea to see if it was actually possible to do, but it soon developed into a full-blown PHP
		class. To learn more about how the doomsday algorithm works, visit the wikipedia article
		here: http://wikipedia.org/wiki/Doomsday_algorithm
		
		Note: this could possibly be made better with list() and array_chunk() functions
	
		Version:	0.9.1
		Updated:	2014-01-29
		Author:		
		Website:	
	
	[ CLASS VARIABLES ]
		calcMethod	= This is the calculation method for determining days within the class. As of
					  this version, only the 'standard' method works properly.
		
		labels		= Enables or disables the use of text labels for months and days. Labels are
					  supplied within each array under a text index as to prevent unwanted result
					  when looping numerically through returned arrays. This will allow multiple
					  calendars to be requested from the object with no need for redefining this
					  setting.
		
		days		= A textual array of full day names; this is used both for returning labels as
					  well as finding anchor day indices.
		
		months		= A textual array of full month names; this is used primarily for labels when
					  they are requested.
	
	[ METHODS ]
		anchorDay	- returns the anchor day index of specified year
			vars ( int $year {YYYY} | string $day {"Dayname"} )
		
		doomsday	- returns the doomsday index for a given year
			vars ( int $year {YYYY} [ string $calculation {"method"} ] )
		
		doomsdates	- returns all doomsedays in the year or within specified month
			vars ( int $year {YYYY} [ int $month {M or MM} ] )
		
		dayOfWeek	- returns day of week index I.A.W. $this->days["Dayname"]
			vars ( int $year {YYYY} | int $month {M or MM} | int $day {D or DD} )
		
		getDays		- returns number of days in a given month (int) or from all months (array)
			vars ( int $year {YYYY} [ int $month {M or MM} ] )
		
		getWeek		- returns week in array format >   week[$i] = (day-0,   day-1,  ...  day-6)
			vars ( int $year {YYYY} | int $month {M or MM} | int $day {D or DD} )
		
		getMonth	- returns month in array format > month[$i] = (week-0,  week-1, ... week-n)
			vars ( int $year {YYYY} | int $month {M or MM} )
		
		getYear		- returns year in array format >   year[$i] = (month-1, month-2,...month-12)
			vars ( int $year {YYYY} ) 
		
		echoMonth	- echos month calendar array retrieved from getMonth() in <table> format
			vars ( array $calendar [ int $dayLength ] )
		
		echoYear	- echos entire year calendar array retrieved from getYear() in <table> format
			vars ( array $calendar )
	*/
	function __construct() {
		$this->calcMethod = 'standard';
		$this->labels = true;
		$this->days = array(
			0 => "Sunday",
			1 => "Monday",
			2 => "Tuesday",
			3 => "Wednesday",
			4 => "Thursday",
			5 => "Friday",
			6 => "Saturday");
		$this->months = array(
			1 => "January",
			2 => "February",
			3 => "March",
			4 => "April",
			5 => "May",
			6 => "June",
			7 => "July",
			8 => "August",
			9 => "September",
			10 => "October",
			11 => "November",
			12 => "December");
	}
	function anchorDay($year, $day = "Thursday") {
		// calculate century of year
		$c = intval(substr($year, 0, 2)) + 1;
		
		// get day offset I.A.W. $this->days
		$t = array_keys($this->days, $day);
		
		// calculate anchor index
		$anchor = (((5 * $c) + floor(($c - 1) / 4)) + $t[0]) % 7;
		
		return $anchor;
	}
	function doomsday($year, $calculation = null) {
		$calculation = (!isset($calculation)) ? $this->calcMethod : $calulation;
		if ($calculation == 'standard') {
			$y = intval(substr($year, -2));		// get last two digits of year
			$anchor = $this->anchorDay($year);	// get anchorday for century
			$a = floor($y / 12);
			$b = $y % 12;
			$c = floor($b / 4);
			$d = ($a + $b + $c) % 7;			// get the sum modulo 7
			$doomsday = ($d + $anchor) % 7;		// modulo 7 with anchor
		}
		// doesn't work
		if ($calculation == 'gregorian') {
			$anchor = $this->anchorDay($year, "Tuesday");
			$d = $anchor + $year + floor($year / 4) - floor($year / 100) + floor ($year / 400);
			$doomsday = $d % 7;
		}
		// doesn't work
		if ($calculation == 'julian') {
			$anchor = $this->anchorDay($year, "Sunday");
			$d = $anchor + $year + floor($year / 4);
			$doomsday = $d % 7;
		}
		
		return $doomsday;
	}
	function doomsdates($year, $month = null) {
		$dates = array(
			// differintiate between leap/common years
			 1 => ($year % 4 == 0) ? array(4, 11, 18, 25) : array(3, 10, 17, 24, 31),
			 2 => ($year % 4 == 0) ? array(1, 8, 15, 22, 29) : array(7, 14, 21, 28),
			// else the other months are fine
			 3 => array(7, 14, 21, 28),
			 4 => array(	4, 11, 18, 25),
			 5 => array(2,  9, 16, 23, 30),
			 6 => array(	6, 13, 20, 27),
			 7 => array(4, 11, 18, 25),
			 8 => array(1,  8, 15, 22, 29),
			 9 => array(5, 12, 19, 26),
			10 => array(3, 10, 17, 24, 31),
			11 => array(7, 14, 21, 28),
			12 => array(5, 12, 19, 26));
		
		// retrieve specific month as needed
		$dates = (isset($month)) ? $dates[$month] : $dates;
		
		return $dates;
	}
	function dayOfWeek($year, $month, $day) {
		// get month doomsdates
		$doomsdates = $this->doomsdates($year, $month);
		$doomsdate = $doomsdates[3];
		$doomsday = $this->doomsday($year);
		
		// number of days between supplied date and doomsday
		$diff = $day - $doomsdate;
		// offset number if less than 1
		$offset = ($diff < 1) ? $diff + 35 : $diff;
		// determine day of week by modulo remainder
		$dayOfWeek = ($offset + $doomsday) % 7;
		
		return $dayOfWeek;
	}
	function getDays($year, $month = null) {
		$days = array(
			 1 => 31,
			 2 => ($year % 4 != 0) ? 28 : 29,
			 3 => 31,
			 4 => 30,
			 5 => 31,
			 6 => 30,
			 7 => 31,
			 8 => 31,
			 9 => 30,
			10 => 31,
			11 => 30,
			12 => 31
		);
		
		// if month is specified
		$days = (isset($month)) ? $days[$month] : $days;
		
		return $days;
	}
	function getWeek($year, $month, $day) {
		$dayOfWeek = $this->dayOfWeek($year, $month, $day);
		
		// if week day labels are enabled
		if ($this->labels) $week['days'] = $this->days;
		
		$date = $day - $dayOfWeek;
		$lastDay = $this->getDays($year, $month);
		for ($wd = 0; $wd < 7; $wd++) {
			$week[$wd] = (0 < $date && $date <= $lastDay) ? $date : "";
			$date++;
		}
		
		return $week;
	}
	function getMonth($year, $month) {
		$lastDay = $this->getDays($year, $month);
		
		// if month labels are enabled
		if ($this->labels) $calendar['month'] = $this->months[$month];
		
		do {
			// add new week to calendar
			$calendar[] = (!isset($day)) ? $this->getWeek($year, $month, 1) : $this->getWeek($year, $month, $day);
			$day = (!isset($day)) ? end(end($calendar)) + 1 : $day + 7;
		} while ($day < $lastDay);
		
		return $calendar;
	}
	function getYear($year) {
		for ($m = 1; $m < 13; $m++) {
			// add new month to calendar
			$calendar[$m] = $this->getMonth($year, $m);
		}
		
		return $calendar;
	}
	function echoMonth($calendar, $dayLength = 3) {
		echo "<table>\n";
		if (!empty($calendar['month'])) echo "\t<caption>".$calendar['month']."</caption>\n";
		// loop through each week
		for ($w = 0; $w < count($calendar[$w]); $w++) {
			// display week day names
			if ($w == 0 and !empty($calendar[$w]['days'])) {
				echo "\t<tr>";
				foreach ($calendar[$w]['days'] as $day) echo "<th>".substr($day, 0, $dayLength)."</th>";
				echo "</tr>\n";
			}
			echo "\t<tr>\n";
			// loop through each day
			for ($d = 0; $d < 7; $d++) {
				echo "\t\t<td>".$calendar[$w][$d]."</td>\n";
			}
			echo "\t</tr>\n";
		}
		echo "</table>\n";		
	}
	function echoYear($calendar) {
		// loop through each month
		for ($m = 1; $m < 13; $m++) {
			$this->echoMonth($calendar[$m]);
		}
	}
}
?>


Is This A Good Question/Topic? 0
  • +

Page 1 of 1