I have a php function to calculate timestamp (start date) to current (end) date that will return 1hr 30min 2s format. What I want to achieve is to calculate only from 8AM to 5PM of a working day. Anything that goes beyond will not be counted. Here is the php code I have.
class duration_computation {
function duration( $time ) {
$d[0] = array(1, "s");
$d[1] = array(60, "min");
$d[2] = array(3600, "hr");
$d[3] = array(86400, "dy");
$d[4] = array(604800, "wk");
$d[5] = array(2592000, "mth");
$d[6] = array(31104000, "yr");
$numbers = array();
$result = "";
$now = time();
$time_difference = ( $now - $time );
$seconds_left = $time_difference;
for ( $i = 6; $i > -1; $i-- ) {
$numbers[$i] = intval( $seconds_left / $d[$i][0] );
$seconds_left -= ( $numbers[$i] * $d[$i][0] );
if ( $numbers[$i] != 0 ) {
$result.= abs($numbers[$i]) . "" . $d[$i][1] . (($numbers[$i]>1)?'':'') ." ";
}
}
return $result;
}
}
$duration = new duration_computation();
echo $duration->duration($trail->duration);
Forget about date(), strtotime(), time(), etc. function, use DateTime :
Use example :
$from = '2013-09-06 15:45:32';
$to = '2013-09-14 21:00:00';
echo some_func_name($from, $to);
Output :
1 day, 22 hours, 14 minutes, 28 seconds
Function :
function some_func_name($from, $to) {
$workingDays = [1, 2, 3, 4, 5]; # date format = N
$workingHours = ['from' => ['08', '00'], 'to' => ['17', '00']];
$start = new DateTime($from);
$end = new DateTime($to);
$startP = clone $start;
$startP->setTime(0, 0, 0);
$endP = clone $end;
$endP->setTime(23, 59, 59);
$interval = new DateInterval('P1D');
$periods = new DatePeriod($startP, $interval, $endP);
$sum = [];
foreach ($periods as $i => $period) {
if (!in_array($period->format('N'), $workingDays)) continue;
$startT = clone $period;
$startT->setTime($workingHours['from'][0], $workingHours['from'][1]);
if (!$i && $start->diff($startT)->invert) $startT = $start;
$endT = clone $period;
$endT->setTime($workingHours['to'][0], $workingHours['to'][1]);
if (!$end->diff($endT)->invert) $endT = $end;
#echo $startT->format('Y-m-d H:i') . ' - ' . $endT->format('Y-m-d H:i') . "\n"; # debug
$diff = $startT->diff($endT);
if ($diff->invert) continue;
foreach ($diff as $k => $v) {
if (!isset($sum[$k])) $sum[$k] = 0;
$sum[$k] += $v;
}
}
if (!$sum) return 'ccc, no time on job?';
$spec = "P{$sum['y']}Y{$sum['m']}M{$sum['d']}DT{$sum['h']}H{$sum['i']}M{$sum['s']}S";
$interval = new DateInterval($spec);
$startS = new DateTime;
$endS = clone $startS;
$endS->sub($interval);
$diff = $endS->diff($startS);
$labels = [
'y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
];
$return = [];
foreach ($labels as $k => $v) {
if ($diff->$k) {
$return[] = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
}
}
return implode(', ', $return);
}
This function can be shorter/better; but that is your job now ;)
Related
In $periods array first column is for single day (1 godinu), second is for more then one (2 godine) and third is the same but after 4 days in my country, we say different (5 godina).
And it is different for everything, here is an example for all of them:
year = (1 = godinu), (2,3,4 = godine), (after 4 = godina)
month = (1 = mesec), (2,3,4 = meseca), (after 4 = meseci)
week = (1 = nedelju), (2,3,4 = nedelje), (after 4 = nedelja)
day = (1 = dan), (after 1 = dana)
hour = (1 = sat), (2,3,4 = sata), (after 4 = sati)
minute = (1 = minut), (after 1 = minuta)
second = (1 = sekund), (2,3,4 = sekunde), (after 4 = sekundi)
<?php
function time_elapsed_string($datetime, $full = false) {
$now = new DateTime;
$ago = new DateTime($datetime);
$diff = $now->diff($ago);
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
$periods = array(
'y' => ['godinu', 'godine', 'godina'],
'm' => ['mesec', 'meseca', 'meseci'],
'w' => ['nedelju', 'nedelje', 'nedelja'],
'd' => ['dan', 'dana', 'dana'],
'h' => ['sat', 'sata', 'sati'],
'i' => ['minut', 'minuta', 'minuta'],
's' => ['sekund', 'sekunde', 'sekundi']
);
$parts = array();
foreach ($periods as $k => &$v) {
if ($diff->$k) {
$parts[] = $diff->$k . ' ' . $v[$diff->$k > 1];
}
}
if (!$full) $parts = array_slice($parts, 0, 1);
return $parts ? 'pre ' . implode(', ', $parts) : DATE_NOW;
}
?>
The correct units for each value can easily be chosen using a simple switch statement.
function time_elapsed_string($datetime, $full = false) {
$now = new DateTime;
$ago = new DateTime($datetime);
$diff = $now->diff($ago);
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
$periods = array(
'y' => ['godinu', 'godine', 'godina'],
'm' => ['mesec', 'meseca', 'meseci'],
'w' => ['nedelju', 'nedelje', 'nedelja'],
'd' => ['dan', 'dana', 'dana'],
'h' => ['sat', 'sata', 'sati'],
'i' => ['minut', 'minuta', 'minuta'],
's' => ['sekund', 'sekunde', 'sekundi']
);
$parts = array();
foreach ($periods as $k => $v) {
if ($diff->$k) {
switch ($diff->$k) {
case 1:
$unit = $v[0];
break;
case 2:
case 3:
case 4:
$unit = $v[1];
break;
default:
$unit = $v[2];
}
$parts[] = $diff->$k . ' ' . $unit;
}
}
if (!$full) $parts = array_slice($parts, 0, 1);
return $parts ? 'pre ' . implode(', ', $parts) : DATE_NOW;
}
echo time_elapsed_string('last month -8days -3hours', true);
// pre 1 mesec, 1 nedelju, 1 dan, 2 sata, 59 minuta, 59 sekundi
Hello in the code bellow I'm not really sure how but instead of getting 32 days it returns me 33 days.
Any advices on how to fix it seems to be because of the datetime objects or timestamps.
<?php
$pricesByMonths = [
1 => 3,
2 => 4,
3 => 3,
4 => 5,
5 => 10,
6 => 15,
7 => 20,
8 => 15,
9 => 13,
10 => 10,
11 => 8,
12 => 3,
];
$pickupDate = new DateTime('12/12/2021 19:00', new DateTimezone('UTC'));
$returnDate = new DateTime('1/13/2022 22:00', new DateTimezone('UTC'));
$initialReturnDate = $returnDate;
if($pickupDate->diff($returnDate)->d <= 1) {
$returnDate->add(new DateInterval('P1D'));
}
$pickupDateTimestamp = $pickupDate->getTimestamp();
// get pickup time
$pickup_time = date('H:i:s', $pickupDateTimestamp);
[$hours, $minutes, $seconds] = explode(':', $pickup_time);
$returnDate->setTime($hours, $minutes, $seconds);
$newReturnDate = $returnDate->getTimestamp() + 7200;
if($newReturnDate < $initialReturnDate->getTimestamp()) {
$newReturnDate += 79200;
}
$totalFee = [];
$days = 1;
$periodPrice = 15;
for ($i = $pickupDateTimestamp; $i <= $newReturnDate; $i += 3600) {
$month = date('n', $i);
if (!array_key_exists($month, $totalFee)) {
$totalFee[$month]['fee'] = $periodPrice + $pricesByMonths[$month];
$days = 1;
}
$totalFee[$month]['days'] = $days++;
}
echo '<pre>';print_r($totalFee);die;
Solved it in the end the check to force minimum 2 days was a bit wrong.
$pickupDate = new DateTime($fields['calc_pickup_date'], new DateTimezone('UTC'));
$returnDate = new DateTime($fields['calc_return_date'], new DateTimezone('UTC'));
$dateDiff = $pickupDate->diff($returnDate);
if($dateDiff->m === 0 && $dateDiff->y === 0 && $dateDiff->h === 0 && $dateDiff->d <= 1) {
$returnDate->add(new DateInterval('P1D'));
}
$pickupDateTimestamp = $pickupDate->getTimestamp();
// get pickup time
$pickup_time = $pickupDate->format('H:m:s');
[$hours, $minutes, $seconds] = explode(':', $pickup_time);
$returnDate->setTime($hours, $minutes, $seconds);
$newReturnDate = $returnDate->getTimestamp() + 7200;
if($newReturnDate <= strtotime($fields['calc_return_date'])) {
$newReturnDate += 79200;
}
$totalFee = [];
$days = 1;
$periodPrice = dpd_get_period_price($varId, $fields['order_days']);
for ($i = $pickupDateTimestamp; $i <= $newReturnDate; $i += 3600) {
$month = date('n', $i);
if (!array_key_exists($month, $totalFee)) {
$totalFee[$month]['fee'] = $periodPrice + $pricesByMonths[$month];
$days = 1;
}
$totalFee[$month]['days'] = $days++;
}
i need array like example if can set option for step,start,end is very better
[
[
"07:30:00",
"08:00:00",
],
[
"08:00:00",
"08:30:00",
],
....
[
"23:30:00",
"00:00:00",
],
]
The best solution I guess is:
function timeSteps($step, $start, $end){
$stepHours = substr($step, 0, 2);
$stepMinutes = substr($step, 3, 2);
$stepSeconds = substr($step, 6, 2);
$startTime = Carbon::createFromFormat('H:i:s', $start);
$endTime = Carbon::createFromFormat('H:i:s', $end);
$result = [];
while ($startTime->lt($endTime)) {
$item = [];
array_push($item, $startTime->format('H:i:s'));
$startTime->addHours($stepHours);
$startTime->addMinutes($stepMinutes);
$startTime->addSeconds($stepSeconds);
array_push($item, $startTime->format('H:i:s'));
array_push($result, $item);
}
return $result;
}
And you can call it like:
timeSteps("00:30:00", "08:00:00", "10:00:00")
If you're using Laravel then you might be better off using CarbonInterval as stated by this blog post (by Jan Östlund) : https://janostlund.com/2019-11-03/generate-time-ranges
$intervals = CarbonInterval::minutes($timeStep)->toPeriod($start, $end);
Then you will get an array of Carbon-object which you can use however you want:
foreach ($intervals as $date) {
dump($date->format('H:i'))
}
i do this in laravel and result is ok
function range($lower = 0, $upper = 86400, $step = 3600, $format = '')
{
$times = array();
if ( empty( $format ) ) {
$format = 'g:i a';
}
foreach ( range( $lower, $upper, $step ) as $increment ) {
$increment = gmdate( 'H:i', $increment );
list( $hour, $minutes ) = explode( ':', $increment );
$date = new \DateTime( $hour . ':' . $minutes );
$times[] = $date->format( $format );
}
$times = collect($times)->chunk(2)->map(function($item) {
return $item->values();
});
$new_times = [];
foreach ($times as $key=>$time){
if($key == 0){
$new_times[$key][0] = $time[0];
$new_times[$key][1] = $time[1];
}
else{
$new_times[$key][0] = Carbon::parse($time[0])->subMinutes(30*$key)->format('H:i:s');
$new_times[$key][1] = Carbon::parse($time[1])->subMinutes(30*$key)->format('H:i:s');
}
}
return $new_times;
}
and use :
range(27000, 144000, 1800, 'H:i:s');
There are few possibilities here, but this method will keep it simple...
Create a function to create your sub-array start and end times.
Then, create a range of start and end times, eg: 8:00am to midnight.
By incrementing each by 1800 seconds (half hour) you will get your result..
<?php
function timeRange( $start = 0, $end = 86400, $step = 3600, $format = 'Y-m-d H:i:s' ) {
$times = [];
foreach ( range( $start, $end, $step ) as $inc ) {
$inc = gmdate( 'H:i', $inc );
$date = new DateTime( $inc );
$times[(string) $inc] = $date->format( $format );
}
return $times;
}
$my_times = [];
$range = range(28800, 84600, 1800);
foreach($range as $seconds)
{
$start = $seconds;
$end = $seconds+1800;
$my_times[] = timeRange($seconds, $end, 1800, 'H:i:s');
}
var_dump($my_times);
I am trying to create an array using PHP OOP that basically creates and array for every day, month, year within 2 dates and allocates a ticket and hours worked set at 0 for every single day that has passed.
The code I have used is:
class statisticsClass{
private $DateFrom = null;
private $DateTo = null;
private $startYear = null;
private $startMonth = null;
private $startDay = null;
private $endYear = null;
private $endMonth = null;
private $endDay = null;
private $theDateDif = null;
private $stages = null;
private function makeDates(){
if(!empty($this->DateFrom)){
$this->DateFrom = $this->generals->convertDate($this->DateFrom);
} else {
$this->DateFrom = date('Y-m-d', strtotime('last year')) . ' 00:00:00';
}
if(!empty($this->DateTo)){
$this->DateTo = $this->generals->convertDate($this->DateTo);
} else {
$this->DateTo = date('Y-m-d', strtotime('now')) . ' 23:59:59';
}
list($theDate, $theTime) = explode(' ', $this->DateFrom);
list($this->startYear, $this->startMonth, $this->startDay) = explode('-', $theDate);
list($theDate2, $theTime2) = explode(' ', $this->DateTo);
list($this->endYear, $this->endMonth, $this->endDay) = explode('-', $theDate2);
}
private function removeZeros($number){
return ltrim($number, '0');
}
private function chartItemVersion(){
if($this->theDateDif <= 31){
$this->stages = 'daily';
} elseif($this->theDateDif > 31 && $this->theDateDif <= 183){
$this->stages = 'weekly';
} else {
$this->stages = 'monthly';
}
}
private function addZeros($number){
if($number < 10){
return '0' . $number;
}
return $number;
}
private function makingQueryArray(){
for($yearMake=$this->startYear; $yearMake<=$this->endYear; $yearMake++){
$this->queryArray[] = intval($yearMake);
}
foreach($this->queryArray as $year){
if($year === $this->startYear){
$currentMonth = intval($this->removeZeros($this->startMonth));
for($currentMonth; $currentMonth <= 12;$currentMonth++){
$this->queryArray[$year][] = (string)$this->addZeros($currentMonth);
$tempHowManyDays = cal_days_in_month(CAL_GREGORIAN, $this->addZeros($currentMonth), $year);
if($this->startYear === $this->addZeros($currentMonth)){
$currentDay = intval($this->removeZeros($this->startDay));
for($currentDay; $currentDay <= $tempHowManyDays; $currentDay){
$this->queryArray[$year][(string)$this->addZeros($currentMonth)][(string)$this->addZeros($currentDay)]['ticket'] = 0;
$this->queryArray[$year][(string)$this->addZeros($currentMonth)][(string)$this->addZeros($currentDay)]['Hours'] = 0;
}
} else {
for($i=1; $i<=$tempHowManyDays; $i++){
$this->queryArray[$year][(string)$this->addZeros($currentMonth)][(string)$this->addZeros($i)]['ticket'] = 0;
$this->queryArray[$year][(string)$this->addZeros($currentMonth)][(string)$this->addZeros($i)]['Hours'] = 0;
}
}
}
} elseif($year === $this->endYear) {
$endMonth = intval($this->removeZeros($this->endMonth));
for($a=1; $a <= $endMonth; $a++){
$this->queryArray[$year][] = (string)$this->addZeros($a);
if($a === $endMonth){
$tempHowManyDays = intval($this->removeZeros($this->endDay));
} else {
$tempHowManyDays = cal_days_in_month(CAL_GREGORIAN, $this->addZeros($a), $year);
}
for($b=1; $b<=$tempHowManyDays; $b++){
$this->queryArray[$year][(string)$this->addZeros($a)][(string)$this->addZeros($b)]['ticket'] = 0;
$this->queryArray[$year][(string)$this->addZeros($a)][(string)$this->addZeros($b)]['Hours'] = 0;
}
}
} else {
for($a=1; $a <= 12; $a++){
$this->queryArray[$year][] = (string)$this->addZeros($a);
$tempHowManyDays = cal_days_in_month(CAL_GREGORIAN, $this->addZeros($a), $year);
for($b=1; $b<=$tempHowManyDays; $b++){
$this->queryArray[$year][(string)$this->addZeros($a)][(string)$this->addZeros($b)]['ticket'] = 0;
$this->queryArray[$year][(string)$this->addZeros($a)][(string)$this->addZeros($b)]['Hours'] = 0;
}
}
}
}
var_dump($this->queryArray);
}
private function dateDifference(){
$now = strtotime($this->DateFrom);
$your_date = strtotime($this->DateTo);
$datediff = $your_date - $now;
$this->theDateDif = round($datediff / (60 * 60 * 24));
}
function __construct($pdo, $theArray, $generals = null){
if($generals !== null){ $this->generals = $generals; }
$this->pdo = $pdo;
if(isset($theArray['DateFrom']) && !empty($theArray['DateFrom'])){ $this->DateFrom = $theArray['DateFrom']; }
if(isset($theArray['DateTo']) && !empty($theArray['DateTo'])){ $this->DateTo = $theArray['DateTo']; }
$this->makeDates();
$this->dateDifference();
$this->chartItemVersion();
$this->makingQueryArray();
var_dump($this->queryArray);
}
}
$theArray = array();
$amhStatistics = new statisticsClass($pdo, $theArray, $generals);
I have been playing around with it for a while and can not get this array to function corectly.
The array should look like this:
array(){
'2018' => array(
01 => array(
01 => array(
'ticket' => 0,
'hours' => 0,
),
02 => array(
'ticket' => 0,
'hours' => 0,
)
)
)
}
As stated the only stipulation is that the start date should start at the start date and the end date should start at the end date.
Could someone point me in the right direction.
Cheers.
Your makingQueryArray function seems complicate - I believe you should solve it differently.
You can use dateperiod to get all days between 2 dates:
$startDate = '2010-10-01';
$endDate = '2010-10-05';
$period = new DatePeriod(new DateTime($startDate), new DateInterval('P1D'), new DateTime($endDate));
Now You can loop on all days and set you array:
foreach ($period as $key => $value) {
$d = explode("-", $value->format('Y-m-d'));
$res[$d[0]][$d[1]][$d[2]] = array('ticket' => 0, 'hours' => 0);
}
$res will give you your desire output. Live example: 3v4l
I've searched around for calendars that is on PHP but all I searched are date time picker.
But what I only want is a simple calendar that shows me the date, without picking them.
I just need the calendar to display simply like how a normal calendar works in our Operating System, thanks.
Is there any way?
Here's one you can use: http://keithdevens.com/software/php_calendar
<?php
//http://keithdevens.com/software/php_calendar
$time = time();
$today = date('j', $time);
$days = array($today => array(null, null,'<div id="today">' . $today . '</div>'));
$pn = array('«' => date('n', $time) - 1, '»' => date('n', $time) + 1);
echo generate_calendar(date('Y', $time), date('n', $time), $days, 1, null, 0);
// PHP Calendar (version 2 . 3), written by Keith Devens
// http://keithdevens . com/software/php_calendar
// see example at http://keithdevens . com/weblog
// License: http://keithdevens . com/software/license
function generate_calendar($year, $month, $days = array(), $day_name_length = 3, $month_href = NULL, $first_day = 0, $pn = array())
{
$first_of_month = gmmktime(0, 0, 0, $month, 1, $year);
// remember that mktime will automatically correct if invalid dates are entered
// for instance, mktime(0,0,0,12,32,1997) will be the date for Jan 1, 1998
// this provides a built in "rounding" feature to generate_calendar()
$day_names = array(); //generate all the day names according to the current locale
for ($n = 0, $t = (3 + $first_day) * 86400; $n < 7; $n++, $t+=86400) //January 4, 1970 was a Sunday
$day_names[$n] = ucfirst(gmstrftime('%A', $t)); //%A means full textual day name
list($month, $year, $month_name, $weekday) = explode(',', gmstrftime('%m, %Y, %B, %w', $first_of_month));
$weekday = ($weekday + 7 - $first_day) % 7; //adjust for $first_day
$title = htmlentities(ucfirst($month_name)) . $year; //note that some locales don't capitalize month and day names
//Begin calendar . Uses a real <caption> . See http://diveintomark . org/archives/2002/07/03
#list($p, $pl) = each($pn); #list($n, $nl) = each($pn); //previous and next links, if applicable
if($p) $p = '<span class="calendar-prev">' . ($pl ? '' . $p . '' : $p) . '</span> ';
if($n) $n = ' <span class="calendar-next">' . ($nl ? '' . $n . '' : $n) . '</span>';
$calendar = "<div class=\"mini_calendar\">\n<table>" . "\n" .
'<caption class="calendar-month">' . $p . ($month_href ? '' . $title . '' : $title) . $n . "</caption>\n<tr>";
if($day_name_length)
{ //if the day names should be shown ($day_name_length > 0)
//if day_name_length is >3, the full name of the day will be printed
foreach($day_names as $d)
$calendar .= '<th abbr="' . htmlentities($d) . '">' . htmlentities($day_name_length < 4 ? substr($d,0,$day_name_length) : $d) . '</th>';
$calendar .= "</tr>\n<tr>";
}
if($weekday > 0)
{
for ($i = 0; $i < $weekday; $i++)
{
$calendar .= '<td> </td>'; //initial 'empty' days
}
}
for($day = 1, $days_in_month = gmdate('t',$first_of_month); $day <= $days_in_month; $day++, $weekday++)
{
if($weekday == 7)
{
$weekday = 0; //start a new week
$calendar .= "</tr>\n<tr>";
}
if(isset($days[$day]) and is_array($days[$day]))
{
#list($link, $classes, $content) = $days[$day];
if(is_null($content)) $content = $day;
$calendar .= '<td' . ($classes ? ' class="' . htmlspecialchars($classes) . '">' : '>') .
($link ? '' . $content . '' : $content) . '</td>';
}
else $calendar .= "<td>$day</td>";
}
if($weekday != 7) $calendar .= '<td id="emptydays" colspan="' . (7-$weekday) . '"> </td>'; //remaining "empty" days
return $calendar . "</tr>\n</table>\n</div>\n";
}
?>
It's a pretty basic mini calendar. No fancy functions.
I have written just one such with PHP5 + ajax(if you are need to use it):
<?php
class PN_Calendar {
public $first_day_of_week = 0; //0 - sunday, 1 - monday
public $current_year = null;
public $current_month = null;
public $current_day = null;
public $show_year_selector = true;
public $min_select_year = 1991;
public $max_select_year = 2045;
public $show_month_selector = true;
public function __construct($atts = array()) {
if (isset($atts['first_day_of_week'])) {
$this->first_day_of_week = $atts['first_day_of_week'];
}
if (!isset($atts['year'])) {
$this->current_year = date('Y');
} else {
$this->current_year = $atts['year'];
}
if (!isset($atts['month'])) {
$this->current_month = date('m');
} else {
$this->current_month = $atts['month'];
}
if (!isset($atts['day'])) {
$this->current_day = date('d');
} else {
$this->current_day = $atts['day'];
}
//***
if (isset($atts['show_year_selector'])) {
$this->show_year_selector = $atts['show_year_selector'];
}
if (isset($atts['show_month_selector'])) {
$this->show_month_selector = $atts['show_month_selector'];
}
if (isset($atts['min_select_year'])) {
$this->min_select_year = $atts['min_select_year'];
}
if (isset($atts['max_select_year'])) {
$this->max_select_year = $atts['max_select_year'];
}
}
/*
* Month calendar drawing
*/
public function draw($data = array(), $y = 0, $m = 0) {
//***
if ($m == 0 AND $m == 0) {
$y = $this->current_year;
$m = $this->current_month;
}
//***
$data['week_days_names'] = $this->get_week_days_names(true);
$data['cells'] = $this->generate_calendar_cells($y, $m);
$data['month_name'] = $this->get_month_name($m);
$data['year'] = $y;
$data['month'] = $m;
return $this->draw_html('calendar', $data);
}
private function generate_calendar_cells($y, $m) {
$y = intval($y);
$m = intval($m);
//***
$first_week_day_in_month = date('w', mktime(0, 0, 0, $m, 1, $y)); //from 0 (sunday) to 6 (saturday)
$days_count = $this->get_days_count_in_month($y, $m);
$cells = array();
//***
if ($this->first_day_of_week == $first_week_day_in_month) {
for ($d = 1; $d <= $days_count; $d++) {
$cells[] = new PN_CalendarCell($y, $m, $d);
}
//***
$cal_cells_left = 5 * 7 - $days_count;
$next_month_data = $this->get_next_month($y, $m);
for ($d = 1; $d <= $cal_cells_left; $d++) {
$cells[] = new PN_CalendarCell($next_month_data['y'], $next_month_data['m'], $d, false);
}
} else {
//***
if ($this->first_day_of_week == 0) {
$cal_cells_prev = 6 - (7 - $first_week_day_in_month); //checked, is right
} else {
if ($first_week_day_in_month == 1) {
$cal_cells_prev = 0;
} else {
if ($first_week_day_in_month == 0) {
$cal_cells_prev = 6 - 1;
} else {
$cal_cells_prev = 6 - (7 - $first_week_day_in_month) - 1;
}
}
}
//***
$prev_month_data = $this->get_prev_month($y, $m);
$prev_month_days_count = $this->get_days_count_in_month($prev_month_data['y'], $prev_month_data['m']);
for ($d = $prev_month_days_count - $cal_cells_prev; $d <= $prev_month_days_count; $d++) {
$cells[] = new PN_CalendarCell($prev_month_data['y'], $prev_month_data['m'], $d, false);
}
//***
for ($d = 1; $d <= $days_count; $d++) {
$cells[] = new PN_CalendarCell($y, $m, $d);
}
//***
//35(7*5) or 42(7*6) cells
$busy_cells = $cal_cells_prev + $days_count;
$cal_cells_left = 0;
if ($busy_cells < 35) {
$cal_cells_left = 35 - $busy_cells - 1;
} else {
$cal_cells_left = 42 - $busy_cells - 1;
}
//***
if ($cal_cells_left > 0) {
$next_month_data = $this->get_next_month($y, $m);
for ($d = 1; $d <= $cal_cells_left; $d++) {
$cells[] = new PN_CalendarCell($next_month_data['y'], $next_month_data['m'], $d, false);
}
}
}
//***
return $cells;
}
public function get_next_month($y, $m) {
$y = intval($y);
$m = intval($m);
//***
$m++;
if ($m % 13 == 0 OR $m > 12) {
$y++;
$m = 1;
}
return array('y' => $y, 'm' => $m);
}
public function get_prev_month($y, $m) {
$y = intval($y);
$m = intval($m);
//***
$m--;
if ($m <= 0) {
$y--;
$m = 12;
}
return array('y' => $y, 'm' => $m);
}
public function get_days_count_in_month($year, $month) {
return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31);
}
public static function get_month_name($m) {
$names = self::get_monthes_names();
return $names[intval($m)];
}
public function get_week_day_name($num, $shortly = false) {
$names = $this->get_week_days_names($shortly);
return $names[intval($num)];
}
public function get_week_days_names($shortly = false) {
if ($this->first_day_of_week == 1) {
if ($shortly) {
return array(
1 => 'Mo',
2 => 'Tu',
3 => 'We',
4 => 'Th',
5 => 'Fr',
6 => 'Sa',
7 => 'Su'
);
}
return array(
1 => 'Monday',
2 => 'Tuesday',
3 => 'Wednesday',
4 => 'Thursday',
5 => 'Friday',
6 => 'Saturday',
7 => 'Sunday'
);
} else {
if ($shortly) {
return array(
0 => 'Su',
1 => 'Mo',
2 => 'Tu',
3 => 'We',
4 => 'Th',
5 => 'Fr',
6 => 'Sa'
);
}
return array(
0 => 'Sunday',
1 => 'Monday',
2 => 'Tuesday',
3 => 'Wednesday',
4 => 'Thursday',
5 => 'Friday',
6 => 'Saturday'
);
}
}
public static function get_monthes_names() {
return 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'
);
}
public function draw_html($view, $data = array()) {
#extract($data);
ob_start();
include('views/' . $view . '.php' );
return ob_get_clean();
}
}
class PN_CalendarCell {
public $cell_year = null;
public $cell_month = null;
public $cell_day = null;
public $in_current_month = true;
public function __construct($y, $m, $d, $in_current_month = true) {
$this->cell_year = $y;
$this->cell_month = $m;
$this->cell_day = $d;
$this->in_current_month = $in_current_month;
}
public function get_week_day_num() {
return date('w', mktime(0, 0, 0, $this->cell_month, $this->cell_day, $this->cell_year)); //from 0 (sunday) to 6 (saturday);
}
public function draw($events) {
$this_day_events = 0;
if (is_array($events)) {
if (isset($events[$this->cell_year][$this->cell_month][$this->cell_day])) {
$this_day_events = count($events[$this->cell_year][$this->cell_month][$this->cell_day]);
}
} else {
$events = array();
}
?>
<span class="pn_cal_cell_ev_counter" <?php if ($this_day_events <= 0): ?>style="display: none;"<?php endif; ?>><?php echo $this_day_events ?></span>
<a data-year="<?php echo $this->cell_year ?>" data-month="<?php echo $this->cell_month ?>" data-day="<?php echo $this->cell_day ?>" data-week-day-num="<?php echo $this->get_week_day_num() ?>" href="javascript:void(0);" class="<?php if ($this->in_current_month): ?>pn_this_month<?php else: ?>other_month<?php endif; ?>"><?php echo $this->cell_day ?></a>
}
}
Script calling:
<?php
include_once 'classes/calendar.php';
$calendar = new PN_Calendar();
echo $calendar->draw();
?>
Download script with demo: http://pluginus.net/archives/simple-free-open-source-ajax-php-calendar-script
Demo: http://demo.pluginus.net/calendar/
I also was looking for a simple solution, a PHP class that rendered me a monthly calendar where I could add easily events.
I've found this PHP Calendar http://coreyworrell.com/calendar/
You have to still create a view/template in html, but you can find a CSS and HTML version there that you can use.
And it has custom events also in PHP
$event = $calendar->event()
->condition('timestamp', strtotime('January 2, 2010'))
->title('Hello All')
->output('My Custom Event')
->add_class('custom-event-class');