PHP calendar: Iterating through selected months? - php

been looking at this for a bit and now my eyes are crossed. :)
I have a calendar script that I found on snipplr.com It's pretty sweet. Props to the creators. Now, I have two things I want to customize.
Right now, the calendar spits out 12 months, January to December. And also the week ends on Sunday (grrrr). I am attempting to make it go from THIS MONTH, plus x number of months. For example, it would display December, plus 5 more months, so Dec, Jan, Feb, March, April, May.
I can tell in the code it uses a $i iteration to get through the months and display the appropriate dates. for($i=1;$i<=11;$i++)
SO, I tried changint it to this: for($i=$this_month;$i<=11;$i++)
$this_month of course being the date('m');
It does successfully display December, but no months after it. (Since it stops at 11). But if I up the 11 to another variable of $this_month+5, then the script doesnt know what months 13, 14 and 15 are.
Any help on this one? Here is the entire script I have thusfar.
function days_in_month($month, $year) {
if($month!=2) {
if($month==9||$month==4||$month==6||$month==11)
return 30;
else
return 31;
}
else
return $year%4==""&&$year%100!="" ? 29 : 28;
}
global $months;
$months = array(0 => 'January', 1 => 'February', 2 => 'March', 3 => 'April', 4 => 'May', 5 => 'June', 6 => 'July', 7 => 'August', 8 => 'September', 9 => 'October', 10 => 'November', 11 => 'December');
$days = array(0 => 'Monday', 1 => 'Tuesday', 2 => 'Wednesday', 3 => 'Thursday', 4 => 'Friday', 5 => 'Saturday', 6 => 'Sunday');
function render_calendar($this_year = null) {
if($this_year==null)
$this_month = date('m')-1;
$first = strtotime(date('m'));
$last = strtotime("+6 months", $this_month);
$this_year = date('Y');
$day_of_the_month = date('N', strtotime('1 January '.$this_year));
for($i=$this_month;$i<=12;$i++) {
// echo $i;
// if ($i==12) {
// $i = 0;
// }
echo $i;
echo "<table>
<caption>".$GLOBALS['months'][$i]."</caption>
<thead>
<tr>
<th>Sun</th>
<th>Mon</th>
<th>Tue</th>
<th>Wed</th>
<th>Thu</th>
<th>Fri</th>
<th>Sat</th>
</tr>
</thead>
<tbody>
<tr>";
for($n=1;$n<$day_of_the_month;$n++)
echo "<td></td>\n";
$days = days_in_month($i+1, $this_year);
$day = 0;
while($day<$days) {
if($day_of_the_month==8) {
echo ($day == 0 ? "" : "</tr>\n") . "<tr>\n";
$day_of_the_month = 1;
}
echo "<td style=\"border: 1px solid red;\">" . ($day+1) . "</td>\n";
$day_of_the_month++;
$day++;
}
echo "</tr>
</tbody>
</table>";
}
}

How about this for your loop:
for($i=$this_month;$i<=$this_month+5;$i++) {
// create a variable to hold the proper month index
$currentMonth = $i;
if ($i>11) {
$currentMonth -= 12;
}
// now replace all references to the $i index with $currentMonth
...
}

Related

PHP- Carbon Datetime DiffInSeconds and How to Group By Hour

I'm calculating difference between 2 datetimes in seconds but I want to group them by hours. It should be like that.
This is how I'm getting difference between 2 dates.
$date_diff = $first->created_at->diffInSeconds($second->created_at);
And For example first time is 09:47:20 and next one is 11:47:50 I need the group them by hour like this.
In 09:00 = 12.40 Minutes
In 10:00 = 60.00 Minutes
In 11:00 = 47.50 Minutes
How can I do that ? And what you'll suggest for this ?
Thanks
You can check out the code below.
Keep in mind that it works as expected if the start time <= the end time.
Also, there's room for improvement, like extracting logic to separate functions or adding trailing/leading zeros where you'd need them, but it should get you started.
$start = '09:47:20';
$end = '11:47:50';
$startTime = Carbon::createFromFormat('H:i:s', $start);
$endTime = Carbon::createFromFormat('H:i:s', $end);
$startHour = $startTime->hour; // 9
$endHour = $endTime->hour; // 11
$hourRange = range($startHour, $endHour); // array(9, 10, 11)
if (count($hourRange) === 1) {
// start and end time share the same hour
$hourRange = array($startHour, $endHour);
}
$lastIndex = count($hourRange) - 1;
$diffGrouped = array();
foreach ($hourRange as $index => $hour) {
if ($index === 0) {
// start hour has the next full hour - calculate the difference
$nextFullHour = $startHour + 1;
$nextFullHourTime = Carbon::createFromFormat('H', $nextFullHour);
$minutes = $startTime->diff($nextFullHourTime)->format('%i.%s');
} else if ($index === $lastIndex) {
// end hour is its own "previous full hour"
$previousFullHourTime = Carbon::createFromFormat('H', $endHour);
$minutes = $endTime->diff($previousFullHourTime)->format('%i.%s');
} else {
// everything between the start and the end hour
$minutes = '60.00';
}
$diffGrouped[] = array(
'hour' => $hour,
'minutes' => $minutes
);
}
dd($diffGrouped);
/*
array:3 [
0 => array:2 [
"hour" => 9
"minutes" => "12.40"
]
1 => array:2 [
"hour" => 10
"minutes" => "60.00"
]
2 => array:2 [
"hour" => 11
"minutes" => "47.50"
]
]
*/

repeat event by days with occurrences

<?php
function getDateOfWeekDay($day) {
$weekDays = array(
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
);
$dayNumber = array_search($day, $weekDays);
$currentDayNumber = date('w', strtotime('today'));
// if ($dayNumber > $currentDayNumber) {
if ( $currentDayNumber > $dayNumber) {
//return date('Y-m-d', strtotime($day));
echo date('Y-m-d',strtotime($day.' this week'));
} else {
//return date('Y-m-d', strtotime($day) + 604800);
echo date('Y-m-d',strtotime($day.' next week') +1);
}
}
$ron="0,2,6"; // $ron is repeats on every sunday , tuesday, and saturday
$oc=4; // $oc is an occurrences how many time it will repeat
$ronS=explode(',', $ron);
foreach($ronS as $ronS) {
$res[]= $ronS;
}
$r=0;
$rr=0;
for($i = 0; $i < $oc; $i++)
{
if($i<count($res))
{
$t=$res[$i];
$r++;
}
else
{
$t=$res[$rr];
$rr++;
}
$week = array('0'=>"Sunday","1"=>"Monday","2"=>"Tuesday","3"=>"Wednesday","4"=>"Thursday","5"=>"Friday","6"=>"Saturday");
$day[] = $week[$t];
}//for
print_r($day);
foreach ($day as $da)
{
echo getDateOfWeekDay($da)."\n";
}
?>
the output of this code is
Array
(
[0] => Sunday
[1] => Tuesday
[2] => Saturday
[3] => Sunday
)
2014-05-18
2014-05-20
2014-05-24
2014-05-18
All working fine but the last date 2014-05-18 is wrong it will be 2014-05-25

PHP Conditionally Combining Arrays

I'm looping through an array of days in the current month to generate another array of days that are on or after the current day. I'm also doing the same for the next month (which will always include all days as they are after the current date).
The complexity is when the next month is in a different year to the current month. The format of the final array is like this:
array("year" => array("month" => array(days)));
When both months are in the same year it might look like this:
$allDays = array("2013" => array( "11" => array(28,29,30), "12" => array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31)));
When the 2 months are in different years (i.e. Dec and Jan) it might look like this:
$allDays = array("2013" => array("12" => array(2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31)), "2014" => array("1" => array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31) )) ;
Here's my code that generates the list of dates for the current month and the next month:
// Set the default timezone
date_default_timezone_set('Australia/Sydney');
// Get days for current month
$day = date("Y-m-d");
$i = strtotime($day);
array("year" => array("month" => array(days)));
$linked_days = array(
date('Y', $i) => array(
date('m') => range(date('d', $i), intval(date('t'))),
),
);
// Get days for next month
$day2 = date("Y-m-d", strtotime('first day of next month')) ;
$i2 = strtotime($day2);
array("year" => array("month" => array(days)));
$linked_days2 = array(
date('Y', $i2) => array(
date('m') => range(date('d', $i2), intval(date('t'))),
),
);
I'm not sure how to go about combining them into the 1 array with a different sytanx if they are in the same year or not?
You can check if there is already an entry for the year in your array with isset function :
Change this
$day2 = date("Y-m-d", strtotime('first day of next month')) ;
$i2 = strtotime($day2);
array("year" => array("month" => array(days)));
$linked_days2 = array(
date('Y', $i2) => array(
date('m') => range(date('d', $i2), intval(date('t'))),
),
);
To
$day2 = date("Y-m-d", strtotime('first day of next month')) ;
$i2 = strtotime($day2);
array("year" => array("month" => array(days))); //useless line ??
if(!isset($linked_days[date('Y', $i2)])){
//if no entry for this year in array, create new entry
$linked_days[date('Y', $i2)] = array(date('m') => range(date('d', $i), intval(date('t'))));
}
else{
//else, just add the month entry
$linked_days[date('Y', $i2)][date('m')] = range(date('d', $i2), intval(date('t'))) ;
}

Most efficient way to get array of months in array of years

What is the most efficient way to get an array of months, from a specified date, up until the present day, grouped by year.
Eg getMonths("August 2012") would output
array(
array("Year"=>"2013", "months" = array(
"February", "January")
),
array("Year"=>"2012", "months" = array(
"December", "November","October", "September", "August")
)
)
So far I've got:
$start = strtotime('2012-08-01');
$end = time();
$month = $start;
$months[] = date('F', $start);
while($month <= $end) {
$month = strtotime("+1 month", $month);
$months[] = date('F', $month);
}
This is outputting the correct months, but not grouping them into years.
Thanks
You can try
function getMonths($month,$count = 1) {
$now = new DateTime();
$start = DateTime::createFromFormat("F Y", $month);
$list = array();
$interval = new DateInterval(sprintf("P%dM",$count));
while ( $start <= $now ) {
$list[$start->format("Y")][] = $start->format("F");
$start->add($interval);
}
return $list;
}
print_r(getMonths("August 2012"));
Output
Array
(
[2012] => Array
(
[0] => August
[1] => September
[2] => October
[3] => November
[4] => December
)
[2013] => Array
(
[0] => January
[1] => February
)
)
Since the answer posted here did not work for me (also tried online sandbox to be sure) i wrote a method that works with the very most versions of PHP:
function getMonths($monat, $year) {
$list = array();
for(;$monat <= 12;$monat++) {
if($year == date("Y") && $monat == date("m")) { // exit on current month+year
break;
}
if(!isset($list[ $year ])) {
$list[ $year ] = array();
}
$list[ $year ][ str_pad($monat, 2, '0', STR_PAD_LEFT) ] = date("F", strtotime('01.' . $monat . '.' . $year));
if($monat == 12) {
$monat = 0;
$year++;
}
}
return $list;
}

php function for get all mondays within date range

Example:
$startDate is Monday 2007-02-05 and $endDate is Tuesday 2007-02-20. Then I want it to list:
Monday 2007-02-05
Monday 2007-02-12
Monday 2007-02-19
I looked at the PHP manual and found this to get all the days between two dates. But how to do it the way i want? PHP Code:
Rather than get all days and loop through them all, get the first Monday after the start date and then iterate 7 days at a time:
$endDate = strtotime($endDate);
for($i = strtotime('Monday', strtotime($startDate)); $i <= $endDate; $i = strtotime('+1 week', $i))
echo date('l Y-m-d', $i);
I needed the same and created a simple method.
public function getMondaysInRange($dateFromString, $dateToString)
{
$dateFrom = new \DateTime($dateFromString);
$dateTo = new \DateTime($dateToString);
$dates = [];
if ($dateFrom > $dateTo) {
return $dates;
}
if (1 != $dateFrom->format('N')) {
$dateFrom->modify('next monday');
}
while ($dateFrom <= $dateTo) {
$dates[] = $dateFrom->format('Y-m-d');
$dateFrom->modify('+1 week');
}
return $dates;
}
Then use it.
$dateFromString = '2007-02-05';
$dateToString = '2007-02-20';
var_dump($this->getMondaysInRange($dateFromString, $dateToString));
Result:
array (size=3)
0 => string '2007-02-05' (length=10)
1 => string '2007-02-12' (length=10)
2 => string '2007-02-19' (length=10)
Maybe it will be helpful for somebody.
You can use below function to get a array of dates between a date range of specific day.
You have to input start date, end date and day number in number.The day number is as follow.
1 = Monday, 2 = Tuesday, 3 = Wednesday, 4 = Thursday. 5 = Friday, 6 = Saturday, 7 = Sunday.
function getDateForSpecificDayBetweenDates($startDate,$endDate,$day_number){
$endDate = strtotime($endDate);
$days=array('1'=>'Monday','2' => 'Tuesday','3' => 'Wednesday','4'=>'Thursday','5' =>'Friday','6' => 'Saturday','7'=>'Sunday');
for($i = strtotime($days[$day_number], strtotime($startDate)); $i <= $endDate; $i = strtotime('+1 week', $i))
$date_array[]=date('Y-m-d',$i);
return $date_array;
}
for ($i = strtotime($startDate); $i <= strtotime($endDate); $i = strtotime('+1 day', $i)) {
if (date('N', $i) == 1) //Monday == 1
echo date('l Y-m-d', $i); //prints the date only if it's a Monday
}
i Create A class, You get All Days In range Date Group By Name of Day:
class DayHelper{
const MONDAY = 'Mon';
const TUESDAY = 'Tue';
const WEDENSDAY = 'Wed';
const THURSDAY = 'Thu';
const FRIDAY = 'Fri';
const SATURDAY = 'Sat';
const SUNDAY = 'Sun';
public function GetYeardays($dateStart, $dateend){
$period = new \DatePeriod(
new \DateTime($dateStart), new \DateInterval('P1D'), (new \DateTime($dateend))
);
$dates = iterator_to_array($period);
$arrayreturn = array();
foreach ($dates as $val) {
$date = $val->format('Y-m-d'); //format date
$get_name = date('l', strtotime($date)); //get week day
$day_name = substr($get_name, 0, 3); // Trim day name to 3 chars
switch ($day_name) {
case self::MONDAY:
$MONDAY[] = $date;
$arrayreturn[self::MONDAY] = $MONDAY;
break;
case self::TUESDAY:
$TUESDAY[] = $date;
$arrayreturn[self::TUESDAY] = $TUESDAY;
break;
case self::WEDENSDAY:
$WEDENSDAY[] = $date;
$arrayreturn[self::WEDENSDAY] = $WEDENSDAY;
break;
case self::THURSDAY:
$THURSDAY[] = $date;
$arrayreturn[self::THURSDAY] = $THURSDAY;
break;
case self::FRIDAY:
$FRIDAY[] = $date;
$arrayreturn[self::FRIDAY] = $FRIDAY;
break;
case self::SATURDAY:
$SATURDAY[] = $date;
$arrayreturn[self::SATURDAY] = $SATURDAY;
break;
case self::SUNDAY:
$SUNDAY[] = $date;
$arrayreturn[self::SUNDAY] = $SUNDAY;
break;
}
}
return $arrayreturn;
}
}
The Output will be like this
array (size=7)
'Fri' =>
array (size=5)
0 => string '2016/01/01' (length=10)
1 => string '2016/01/08' (length=10)
2 => string '2016/01/15' (length=10)
3 => string '2016/01/22' (length=10)
4 => string '2016/01/29' (length=10)
'Sat' =>
array (size=5)
0 => string '2016/01/02' (length=10)
1 => string '2016/01/09' (length=10)
2 => string '2016/01/16' (length=10)
3 => string '2016/01/23' (length=10)
4 => string '2016/01/30' (length=10)
'Sun' =>
array (size=4)
0 => string '2016/01/03' (length=10)
1 => string '2016/01/10' (length=10)
2 => string '2016/01/17' (length=10)
3 => string '2016/01/24' (length=10)
'Mon' =>
array (size=4)
0 => string '2016/01/04' (length=10)
1 => string '2016/01/11' (length=10)
2 => string '2016/01/18' (length=10)
3 => string '2016/01/25' (length=10)
'Tue' =>
array (size=4)
0 => string '2016/01/05' (length=10)
1 => string '2016/01/12' (length=10)
2 => string '2016/01/19' (length=10)
3 => string '2016/01/26' (length=10)
'Wed' =>
array (size=4)
0 => string '2016/01/06' (length=10)
1 => string '2016/01/13' (length=10)
2 => string '2016/01/20' (length=10)
3 => string '2016/01/27' (length=10)
'Thu' =>
array (size=4)
0 => string '2016/01/07' (length=10)
1 => string '2016/01/14' (length=10)
2 => string '2016/01/21' (length=10)
3 => string '2016/01/28' (length=10)
I made some changes to response https://stackoverflow.com/a/37300272/6871295
Then I can get the days between dates for any day and return format.
public function getWeekDayInRange($weekday, $dateFromString, $dateToString, $format = 'Y-m-d')
{
$dateFrom = new \DateTime($dateFromString);
$dateTo = new \DateTime($dateToString);
$dates = [];
if ($dateFrom > $dateTo) {
return $dates;
}
if (date('N', strtotime($weekday)) != $dateFrom->format('N')) {
$dateFrom->modify("next $weekday");
}
while ($dateFrom <= $dateTo) {
$dates[] = $dateFrom->format($format);
$dateFrom->modify('+1 week');
}
return $dates;
}
This is code for fetching the weekday of "$startdate" and counting the number of weekdays between two dates.
`$startdate` = '2015-03-01';
`$endate` = '2015-03-31';
`$recurringDay` = date('N', strtotime($startdate)); // recurring Day from date i.e monday = 1, Tuesday = 2 ...etc
$begin = new DateTime(`$startdate`);
$end = new DateTime(date('Y-m-d',strtotime('+1 day', strtotime($endate))));
while($begin format('Y-m-d');
$day[] = $begin->format('N');
$begin->modify('+1 day');
}
$c=0; // counter starts
foreach($day as $key=>$dt) {
if ($dt==`$recurringDay`) // compare it
{
$k[] = $key;
$c++;
}
}
`$nofDays` = $c; // number of mondays , tuesday
foreach($k as $pp) {
//adding session code
`$recurringDatetime[]` = $period[$pp]; // recurring dates
}
print_r(`$recurringDatetime`); // array of dates of monday, tuesday ..etc
$dates = array();
$dates[] = strtotime($start);
for($i = 0; $i <= 12; $i++){
$dates[] = strtotime('+1 week', $dates[$i]);
}
foreach($dates as $date){ echo date("d.m.Y", $date); }
I had similar issue and courses can start on any day. This script picks starting day and collect next days every week until the wanted amount (12 in this case).
Convert $startDate and $endDate before that to timestamps:
foreach ($date = $startDate; $date <= $endDate; $date += 60 * 60 * 24) {
if (strftime('%w', $date) == 1) {
$mondays[] = strftime('%A %Y-%m-%d', $date);
}
}
simply you can add as,
$date_from = "2007-02-05";
$date_from = strtotime($date_from);
$date_to="2007-02-20";
$date_to = strtotime($date_to);
for ($i=$date_from; $i<=$date_to; $i+=86400) {
$day = date("Y-m-d", $i);
$unixTimestamp = strtotime($day);
$dayOfWeek = date("l", $unixTimestamp);
if ($dayOfWeek == "Monday") {
echo $day ."is a". $dayOfWeek;
}
}//end for

Categories