repeat event by days with occurrences - php

<?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

Related

Calculate Appointments beetween two dates

Situation:
I have arrays with information of the used appointments and the calculated days for the new appointment series based on PHP.
For example, the exist appointment array:
Array
(
[0] => Array
(
[date] => 2019-05-02
[time_start] => 14:00:00
[time_end] => 15:30:00
)
[1] => Array
(
[date] => 2019-05-06
[time_start] => 14:00:00
[time_end] => 15:30:00
)
)
Now, i will check have the calculated series (same array format) collisions with the exist appointments.
My Question:
How can i check if a collision exist beetween the start and end time and if yes how i can give the array a new value with a time windows after or before the exist appointment. This within a time windows from 08:00 am to 4:00 pm.
What i have is the calculation of the appointment days.
private function calculate_dates($data, $measure)
{
$this->load->model('calendar/calendar_model');
$holiday_dates = $this->calendar_model->get_holidays();
foreach ($holiday_dates as $key => $value) {
$holidays[] = $value['holiday_date'];
}
$begin = new DateTime($data->measure_begin);
$end = new DateTime($data->measure_end);
$oneday = new DateInterval("P1D");
$days = json_decode($data->measure_dates);
$wdays = array();
$ue_minutes = 0;
$minutes = ($data->measure_ue * $measure->ue_minutes/2);
$daterange = new DatePeriod( $begin, DateInterval::createFromDateString('+1 weekdays') ,$end );
foreach(new DatePeriod($begin, $oneday, $end->add($oneday)) as $day) {
$day_num = $day->format("N"); /* 'N' number days 1 (mon) to 7 (sun) */
if($day_num < 6 ) { /* weekday */
$wdays[] = $day;
}
}
$count = 1;
foreach($wdays as $date){
foreach ($days as $key => $value) {
if(mb_strtolower($date->format('l')) == $value){
if(($data->measure_ue/2)+1 != $count){
if(in_array($date->format('Y-m-d'), $holidays)) {
$dates[] = $this->close_days($date, $days, true)->format('l, d.m.Y');
} else {
$dates[] = $date->format('l, d.m.Y');
}
$count++;
}
}
}
}
return array(
'dates' => $dates,
'minutes' => round($minutes/count($dates))
);
}
private function close_days($date, $days, $init = false)
{
if($init){
$days[] = 'saturday';
$days[] = 'sunday';
}
if( in_array(mb_strtolower($date->format('l')), $days) ) {
$this->close_days($date->modify('next day'), $days);
}
return $date;
}
Any Ideas for a solution or maybe a code for a better way?

Sort array of days from a specific start date

I have this array of days in a random order :
$jour_planning[] = "friday";
$jour_planning[] = "wednesday";
$jour_planning[] = "monday";
$jour_planning[] = "tuesday";
$jour_planning[] = "thursday";
$jour_planning[] = "sunday";
$jour_planning[] = "saturday";
If we are today a "tuesday", I would like to have this new array :
$jour_planning[] = "wednesday";
$jour_planning[] = "thursday";
$jour_planning[] = "friday";
$jour_planning[] = "saturday";
$jour_planning[] = "sunday";
$jour_planning[] = "monday";
$jour_planning[] = "tuesday";
How can do that, with usort() ?
Regards,
Vianney
I would first sort the array (and avoid french and english naming :) ).
Then, loop that sorted array and store into 2 separates array the days before the expected one (including this one), and the days after.
And finally, merge both arrays.
There's certainly better ways to do that.
$jour_planning[] = "friday";
$jour_planning[] = "wednesday";
$jour_planning[] = "monday";
$jour_planning[] = "tuesday";
$jour_planning[] = "thursday";
$jour_planning[] = "sunday";
$jour_planning[] = "saturday";
$sorted_days_planning = array(1 => null, 2 => null, 3 => null, 4 => null, 5 => null, 6 => null, 7 => null);
foreach ($jour_planning as $value)
{
$day_of_week = date('N', strtotime($value));
$sorted_days_planning[$day_of_week] = $value;
}
$final_days_planning = array();
$day_to_start = "tuesday";
$day_found = false;
$temp_array = array();
foreach ($sorted_days_planning as $value)
{
if (!$day_found)
{
$temp_array[] = $value;
if ($day_to_start == $value)
$day_found = true;
}
else
$final_days_planning[] = $value;
}
$final_days_planning = array_merge($final_days_planning, $temp_array);
var_dump($final_days_planning);
Outputs :
array(6) {
[0]=> string(9) "wednesday"
[1]=> string(8) "thursday"
[2]=> string(6) "friday"
[3]=> string(8) "saturday"
[4]=> string(6) "sunday"
[5]=> string(6) "monday"
[6]=> string(7) "tuesday"
}
You can rearrange your array using uksort(), date() and strtotime().
function sort_week_days( $t1, $t2 ) {
$weekdays = array( 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday' );
foreach ( $weekdays as $key => $value ) {
$weekdays[ $key ] = date( 'w', strtotime( $value ) );
}
$t1_time = date( 'w', strtotime( strtolower( $t1 ) ) );
$t2_time = date( 'w', strtotime( strtolower( $t2 ) ) );
return array_search( $t1_time, $weekdays ) - array_search( $t2_time, $weekdays );
}
You need to pass your random array as below :
usort($jour_planning, "sort_week_days");
Then you can used your array in below code :
$day = date('w'); // You need to change to date('w', '-1day'); get result from today.
for ($i=0; $i <= $day ; $i++) {
array_push($jour_planning, array_shift($jour_planning));
}
Because of your array is randomly ordered, there is no other way to order it correctly, then doing it by hand (you cannot order the array numerically or alphabetically - it can be done by calculating the days by the datetime() function, see #Cid's answer), so:
/*
$jour_planning = [];
$jour_planning[] = "friday";
$jour_planning[] = "wednesday";
$jour_planning[] = "monday";
$jour_planning[] = "tuesday";
$jour_planning[] = "thursday";
$jour_planning[] = "sunday";
$jour_planning[] = "saturday";
*/
$days = [
0 => 'monday',
1 => 'tuesday',
2 => 'wednesday',
3 => 'thursday',
4 => 'friday',
5 => 'saturday',
6 => 'sunday'
];
$today = array_search(strtolower(date('l')), $days);
$tomorrow = ($today === 6) ? 0 : $today + 1;
$reordered = array_merge(array_slice($days, $tomorrow), array_slice($days, 0, $tomorrow));
print_r($reordered);
Firstly you have to search the current day, then add 1 to the index of this day and you have the day, that will be tomorrow. Now, when you have this index, you simply create 2 arrays: the first one starting from the day of tomorrow and the second one starting from index 0 to the day of today. Then merge this two arrays together and you have exactly what you wanted to have.
You can use this function to sort week days and it's has option to include the first day.
function sort_days($day_to_start = 'monday', $include_first_day = true)
{
$final_days_planning = [];
$rest_days = [];
$first_day_found = 0;
foreach ([ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ] as $day)
{
if (!$first_day_found){
if ($day_to_start == $day){
$first_day_found = 1;
if($include_first_day){
$final_days_planning[] = $day;
}
else
{
$rest_days[] = $day;
}
}
else
{
$rest_days[] = $day;
}
} else{
$final_days_planning[] = $day;
}
}
return array_merge($final_days_planning, $rest_days);
}
To try it:
$days = sort_days('wednesday');
print_r($days);
You can use in_array to find the days present in your array and add to new array.
$jour_planning=["saturday","wednesday","friday","thursday"];
public function getSortedDays($jour_planning){
$sorted_days=[];
for($i=1;$i<=7;$i++){
$day = date("l", strtotime("+$i days"));
$_day = strtolower($day);
if(in_array($_day, $jour_planning)){
$sorted_days[] = $_day;
}
}
return $sorted_days;
}
$sorted_days = getSortedDays($jour_planning);
print_r($sorted_days); //Array ( [0] => wednesday [1] => thursday [2] => friday [3] => saturday )
while (end($jour_planning) !== "tuesday") {
array_unshift($jour_planning, array_pop($jour_planning));
}

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 calendar: Iterating through selected months?

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
...
}

Combine days where opening hours are similar

How might I code a function in PHP (with CodeIgniter) to merge days with similar opening hours of a store together. For example, if we have:
Mon 9am-5pm
Tue 9am-5pm
Wed 9am-5pm
Thu 9am-5pm
Fri 9am-5pm
Sat 9am-7pm
Sun 9am-7pm
I want the code to simplify it to:
Mon-Fri 9am-5pm
Sat-Sun 9am-7pm
How do I do this without a long list of if/else or case ifs? I'm using CodeIgniter..
<?php
$openHours = array(
'Mon' => '9am-5pm',
'Tue' => '9am-5pm',
'Wed' => '9am-9pm',
'Thu' => '9am-5pm',
'Fri' => '9am-5pm',
'Sat' => '9am-7pm',
'Sun' => '9am-7pm'
);
$summaries = array();
foreach ($openHours as $day => $hours) {
if (count($summaries) === 0) {
$current = false;
} else {
$current = &$summaries[count($summaries) - 1];
}
if ($current === false || $current['hours'] !== $hours) {
$summaries[] = array('hours' => $hours, 'days' => array($day));
} else {
$current['days'][] = $day;
}
}
foreach ($summaries as $summary) {
if (count($summary['days']) === 1) {
echo reset($summary['days']) . ' ' . $summary['hours'] . PHP_EOL;
} else {
echo reset($summary['days']) . '-' . end($summary['days']) . ' ' . $summary['hours'] . PHP_EOL;
}
}
codepad sample
If you want it in the following format:
Sun-Tue, Fri-Sat: 11am-12am; Wed: 10am-12am; Thu: 9am-12am
Which will group days and handle different times within the week:
<?php
$open_hours = array (
"Sun" => "11am-12am",
"Mon" => "11am-12am",
"Tue" => "11am-12am",
"Wed" => "10am-12am",
"Thu" => "9am-12am",
"Fri" => "11am-12am",
"Sat" => "11am-12am"
);
$result = [];
foreach ($open_hours as $day => $hours) {
if (empty($result) || $previous !== $hours) {
$result[$hours][] = $day;
} elseif ($previous === $hours) {
$key = array_key_last($result[$hours]);
$current = strtok($result[$hours][$key], '-');
$result[$hours][$key] = $current.'-'.$day;
}
$previous = $hours;
}
// build output (joining days with ,)
$output = [];
foreach ($result as $hours => $days) {
$output[] = implode(', ', $days).': '.$hours;
}
// join with ;'s and output
echo implode('; ', $output);
https://3v4l.org/tKOlI

Categories