Calculate time duration based on shift times - php

I am trying to calculate $work_in_daytime and $work_in_nighttime.
$nightStart = '22:00';
$nightEnd = '07:00';
$workers = array(
'0' => array(
'name' => 'Lyons',
'start' => '15:15',
'end' => '23:45'
),
'1' => array(
'name' => 'Santos',
'start' => '10:00',
'end' => '22:00'
),
'2' => array(
'name' => 'Montgomery',
'start' => '22:30',
'end' => '08:00'
)
);
I have tried following code.
foreach ($workers as $worker) {
$startTime = strtotime($em['start']);
$endTime = strtotime($em['end']);
$length = formattedTime($endTime - $startTime);
$nightTimeStart = strtotime($nightStart);
$nightTimeEnd = strtotime($nightEnd);
$dayTimeLength = 0;
$nightTimeLength = 0;
if ($startTime > $nightTimeStart) {
$nightTimeLength += $startTime - $nightTimeStart;
}
if ($startTime < $nightTimeStart) {
$dayTimeLength += $nightTimeStart - $startTime;
}
if ($endTime > $nightTimeStart) {
$nightTimeLength += $endTime - $nightTimeStart;
}
if ($endTime < $nightTimeStart) {
$dayTimeLength += $endTime - $nightTimeStart;
}
echo 'Day Time: '.$dayTimeLength.PHP_EOL;
echo 'Night Time: '.$nightTimeLength.PHP_EOL;
}
I am stuck with correct calculation.

Try This:
$nightStart = '22:00';
$nightEnd = '07:00';
$workers = array(
'0' => array(
'name' => 'Lyons',
'start' => '15:15',
'end' => '23:45'
),
'1' => array(
'name' => 'Santos',
'start' => '6:00',
'end' => '22:00'
),
'2' => array(
'name' => 'Montgomery',
'start' => '22:30',
'end' => '08:00'
)
);
function timetodate($time)
{
return date('H:i', $time);
}
foreach ($workers as $worker) {
$startTime = strtotime($worker['start']);
$endTime = strtotime($worker['end']);
$length = date('H:i',($endTime - $startTime));
$day = strtotime("24H");
$nightTimeStart = strtotime($nightStart);
$nightTimeEnd = strtotime($nightEnd);
$dayTimeLength = 0;
$nightTimeLength = 0;
/* Night Time Calculations */
if ($endTime <= $startTime) {
if ($startTime >= $nightTimeStart) {
$nightTimeLength += $day - $startTime;
if ($endTime <= $nightTimeEnd) {
$nightTimeLength += $nightTimeEnd - $endTime;
}
else
{
$nightTimeLength += $nightTimeEnd;
}
}
}
elseif ($endTime > $nightTimeStart) {
$nightTimeLength += $endTime - $nightTimeStart;
}
elseif ($startTime < $nightTimeEnd) {
$nightTimeLength += $nightTimeEnd - $startTime;
}
/* Day Time Calculations */
if ($startTime >= $nightTimeEnd) {
if ($endTime <= $nightTimeStart) {
if ($startTime < $endTime) {
$dayTimeLength += $endTime - $startTime;
}
else
{
$dayTimeLength += $endTime - $nightTimeEnd;
}
}
else
{
$dayTimeLength += $nightTimeStart - $startTime;
}
}
else
{
if ($endTime <= $nightTimeStart) {
$dayTimeLength += ($endTime - $nightTimeEnd);
}
else
{
$dayTimeLength += $nightTimeStart - $nightTimeEnd;
}
}
echo "Name:". $worker['name'].PHP_EOL;
echo 'Day Time: '.timetodate($dayTimeLength).PHP_EOL;
echo 'Night Time: '.timetodate($nightTimeLength).PHP_EOL.PHP_EOL;
}
https://www.tehplayground.com/CkZ53jjD1cyFEymB
earlier post:
Disregard ---- https://www.tehplayground.com/PohT0L7s35m9VKOe
Like this?
Although I haven't adjusted it, but i think i need to change it a bit more to get it correctly for the turn of the new day (it doesnt see it as a continous shift i dont think)

The variable $em is undefined.
Unsure of what your constants are for daytime and nighttime, but
assuming you calculate daytime from 6am to 6pm and night time from
6pm to 6am:
<?php
$start_nighttime = strtotime('18:00');
$end_nighttime = strtotime('05:59');
$start_daytime = strtotime('06:00');
$end_daytime = strtotime('17:59');
foreach($worker as $data){
$worker_start = strtotime($data['start']);
$worker_end = strtotime($data['end']);
if ($worker_start > $start_daytime && $worker_end < $start_nighttime) {
//Worked only during the day
$daytime = round(abs($worker_start - $worker_end) / 60, 2);
} elseif ($worker_start > $start_daytime && $worker_end > $end_nighttime) {
//Worked during the day and extended past defined night time
$daytime = round(abs($worker_start - $end_daytime) / 60, 2);
$nighttime = round(abs($start_nightime - $worker_end) / 60, 2);
} elseif ($worker_start > $start_nighttime && $worker_end < $end_nighttime){
//Worked only during the night
$nighttime = round(abs($worker_start - $worker_end));
} elseif ($worker_start > $start_nighttime && $worker_end > $end_nighttime){
//Worked only during the night up until the moring
$nighttime = round(abs($worker_start - $end_nighttime));
$daytime = round(abs($start_daytime - $worker_end));
}
}
?>

Related

How to get every month number and year between two month/year points

I am creating a function where you can give a starting year, month and end year, month and the function will print every month and year in between the two given points.
I've already created a function that works perfectly but I believe this is not a good practice and there might be better way to do this. Now I am seeking your help to find a better way.
P.S. I can't get full date as input. Only can get month number and year.
Here is my code -
function get_all_months($monthstart = null, $yearstart = null, $monthend = null, $yearend = null) {
if (($monthstart === null) || ($yearstart === null) || ($monthend === null) || ($yearend === null)) {
$monthend = date('m');
$yearend = date('Y');
if($monthend < 6) {
$yearstart = $yearend - 1;
$monthstart = (($monthend - 5) + 12);
} else {
$yearstart = $yearend;
$monthstart = $monthend - 5;
}
}
$month_array = array();
if ($yearstart > $yearend) {
for ($m=$monthend; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $yearend);
for ($y=$yearend+1; $y<$yearstart; $y++) for ($m=1; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $y);
for ($m=1; $m<=$monthstart; $m++) $month_array[] = array('month' => $m, 'year' => $yearstart);
} elseif ($yearend > $yearstart) {
for ($m=$monthstart; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $yearstart);
for ($y=$yearstart+1; $y<$yearend; $y++) for ($m=1; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $y);
for ($m=1; $m<=$monthend; $m++) $month_array[] = array('month' => $m, 'year' => $yearend);
} else {
for ($m=$monthstart; $m<=$monthend; $m++) $month_array[] = array('month' => $m, 'year' => $yearstart);
}
return $month_array;
}
EDIT: Based on Nigel Ren's answer, this is the best way I could think of -
function get_all_months($monthstart = null, $yearstart = null, $monthend = null, $yearend = null) {
if (($monthstart === null) || ($yearstart === null) || ($monthend === null) || ($yearend === null)) {
$monthend = date('m');
$yearend = date('Y');
if($monthend < 6) {
$yearstart = $yearend - 1;
$monthstart = (($monthend - 5) + 12);
} else {
$yearstart = $yearend;
$monthstart = $monthend - 5;
}
}
$output = [];
if ($yearstart > $yearend) {
$time = strtotime($yearend."-".$monthend);
$last = date('m-Y', strtotime($yearstart."-".$monthstart));
} else {
$time = strtotime($yearstart."-".$monthstart);
$last = date('m-Y', strtotime($yearend."-".$monthend));
}
do {
$cur_month_year = date('m-Y', $time);
$month = date('m', $time);
$year = date('Y', $time);
$output[] = array('month'=>$month,'year'=>$year);
$time = strtotime('+1 month', $time);
}
while ($cur_month_year != $last);
return $output;
}
You can use PHP's DateInterval class which is used for these purposes. Try this code
<?php
function getMonthsFromRange($start, $end, $format = 'M Y')
{
$array = array();
// Since you wanted 1 month it is Period = 1 Month
$interval = new DateInterval('P1M');
$realEnd = new DateTime($end);
$realEnd->add($interval);
$period = new DatePeriod(new DateTime($start), $interval, $realEnd);
// Use loop to store date into array
foreach ($period as $date)
$array[] = $date->format($format);
// Return the array elements
return $array;
}
// Function call with passing the start date and end date
$months = getMonthsFromRange('2010-10', '2011-11');
print_r($months);
It's output is:
Array ( [0] => Oct 2010 [1] => Nov 2010 [2] => Dec 2010 [3] => Jan 2011 [4] => Feb 2011 [5] => Mar 2011 [6] => Apr 2011 [7] => May 2011 [8] => Jun 2011 [9] => Jul 2011 [10] => Aug 2011 [11] => Sep 2011 [12] => Oct 2011 [13] => Nov 2011 )
Based on the answer here, it can be done simply by adding 1 month to the start date till you get to the end date...
function get_all_months($monthstart = null, $yearstart = null, $monthend = null, $yearend = null) {
$output = [];
$time = strtotime($yearstart."-".$monthstart);
$last = date('m-Y', strtotime($yearend."-".$monthend));
do {
$month = date('m-Y', $time);
$output[] = $month;
$time = strtotime('+1 month', $time);
}
while ($month != $last);
return $output;
}
So
print_r(get_all_months(4,2008,2,2010));
gives...
Array
(
[0] => 04-2008
[1] => 05-2008
[2] => 06-2008
[3] => 07-2008
[4] => 08-2008
[5] => 09-2008
[6] => 10-2008
[7] => 11-2008
[8] => 12-2008
[9] => 01-2009
[10] => 02-2009
[11] => 03-2009
[12] => 04-2009
[13] => 05-2009
[14] => 06-2009
[15] => 07-2009
[16] => 08-2009
[17] => 09-2009
[18] => 10-2009
[19] => 11-2009
[20] => 12-2009
[21] => 01-2010
[22] => 02-2010
)
probably you're looking for something like this:
function get_all_months($monthstart = null, $yearstart = null, $monthend = null, $yearend = null) {
$month_array = [];
if ($yearstart == $yearend)
for ($m=$monthstart; $m<=$monthend; $m++) $month_array[] = array('month' => $m, 'year' => $yearstart);
else {
for ($m=$monthstart; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $yearstart);
for ($y=$yearstart+1; $y<$yearend; $y++) for ($m=1; $m<=12; $m++) $month_array[] = array('month' => $m, 'year' => $y);
for ($m=1; $m<=$monthend; $m++) $month_array[] = array('month' => $m, 'year' => $yearend);
}
return $month_array;
}
If I understand correctly - you get the month as a number and the year as a number e.g 6 and 1997. If we assume that the start year is always less than the end year I would suggest going like this.
function distanceBetweenDates(int $sm, int $sy, int $em, int $ey) {
$monthsBetweenYears = ($ey - $sy + 1) * 12;
$distanceBetweenMonths = $monthsBetweenYears - $sm - (12 - $em);
$startMonth = $sm + 1;
$startYear = $sy;
while ($distanceBetweenMonths > 0) {
if ($startMonth <= 12) {
echo $startMonth . ' - ' . $startYear;
} else {
$startMonth = 1;
$startYear++;
echo $startMonth . ' - ' . $startYear;
}
echo "\n";
$startMonth++;
$distanceBetweenMonths--;
}
}
The only thing you might need to see is if the given months are included or excluded from the calculation.
The only thing missing here is the validation since it can be "skipped" of a sort if you use types inside the method.
With the DateTime class and DateInterval, you can create a generator of DateTime object of the specified range:
<?php
function get_all_months(int $monthstart, int $yearstart, int $monthend, int $yearend) {
$onemonth = new DateInterval('P1M'); // one month interval
$timeperiod = new DatePeriod(
DateTime::createFromFormat('Y-m', "{$yearstart}-{$monthstart}"),
$onemonth,
DateTime::createFromFormat('Y-m', "{$yearend}-{$monthend}")->add($onemonth)
);
foreach ($timeperiod as $pos) {
yield clone $pos;
}
}
foreach (get_all_months(12, 2009, 1, 2020) as $month) {
echo "{$month->format('Y-m')}\n";
}
DateTime should be more flexible to use than plain string or number array (see DateTime::format for more usage options).
Note: inspired by #keidakida, updated my answer.

PHP: Get the sum of a different dates in array

Hello Im just a beginner programmer but Im now building an app which gets the total hours of work.
Here I have a time_start array which the threshold for the customer to in and same as out for time_end
The logs here is where the person checks in.
$time_start = [
[0] => '22:00:00',
[1] => '03:00:00',
];
$time_end = [
[0] => '02:00:00',
[1] => '08:00:00',
];
$logs = [
[0] => '2019-07-09 22:00:00',
[1] => '2019-07-10 02:00:00',
[2] => '2019-07-10 03:00:00',
[3] => '2019-07-10 08:00:00',
];
So I'm trying to get the sum of their hours in night shift which has different date.
Im trying to get it in:
foreach( $logs as $check_time ){
$attendance_date_time = date("Y-m-d",strtotime($check_time));
$time_starts = date('Y-m-d H:i:s', strtotime("$attendance_date_time $time_start"));
$time_ends = date('Y-m-d H:i:s', strtotime("$attendance_date_time $time_end"));
if ( $check_time >= $time_starts && $check_time <= $time_ends )
{
$time[] = $check_time;
}else{
$time = null
}
}
Supposedly I will get all logs because it is between time_start and time_end and store it to $time
And summing the time i get.
Since I'm new at php is their any easiest idea to get the total work hours? Cuz I get a null because the time_end it gets was the date of check_in.
Here is your snippet,
$time_start = [
0 => '22:00:00',
1 => '03:00:00',
];
$time_end = [
0 => '02:00:00',
1 => '08:00:00',
];
$logs = [
0 => '2019-07-09 22:00:00',
1 => '2019-07-10 02:00:00',
2 => '2019-07-10 03:00:00',
3 => '2019-07-10 08:00:00',
];
$time = [];
$diff = 0;
for ($j = 0; $j < count($logs); $j = $j + 2) {
$attendance_start = date("Y-m-d", strtotime($logs[$j]));
$attendance_end = date("Y-m-d", strtotime($logs[$j + 1]));
for ($i = 0; $i < count($time_start); $i++) {
$time_starts = date('Y-m-d H:i:s', strtotime("$attendance_start " . $time_start[$i] . ""));
$time_ends = date('Y-m-d H:i:s', strtotime("$attendance_end " . $time_end[$i] . ""));
if ($logs[$j] >= $time_starts && $logs[$j + 1] <= $time_ends) {
array_push($time, $logs[$j], $logs[$j + 1]);
// calculating diff for two alternate days
$diff += (round((strtotime($logs[$j + 1]) - strtotime($logs[$j])) / 3600, 1));
break;
}
}
}
echo $diff . " Hours";die;
Demo
Output:-
9 Hours
The for loop is the easiest way to do this
$time_start = [
'22:00:00',
'03:00:00',
];
$time_end = [
'02:00:00',
'08:00:00',
];
$logs = [
'2019-07-09 22:00:00',
'2019-07-10 02:00:00',
'2019-07-10 03:00:00',
'2019-07-10 08:00:00',
];
$totalDiff = 0;
for($i =0 ; $i < count($logs); $i = $i + 2)
{
$startDate = strtotime($logs[$i]);
$endDate = strtotime($logs[$i+1]);
$diff = $endDate-$startDate;
$totalDiff += $diff;
}
$hourDiff = $totalDiff / 3600;
echo $hourDiff . ' hours';
Demo

Find recent and upcoming dates

I have a two-dimensional array containing events and dates:
$events = array(
array('event' => 'event1', 'date' => '2016-05-05'),
array('event' => 'event2', 'date' => '2016-05-08'),
array('event' => 'event3', 'date' => '2016-05-08'),
array('event' => 'event4', 'date' => '2016-05-10'),
array('event' => 'event5', 'date' => '2016-05-10'),
array('event' => 'event6', 'date' => '2016-05-11'),
array('event' => 'event7', 'date' => '2016-05-11'),
array('event' => 'event8', 'date' => '2016-05-13')
};
Let's say today is 2016-05-10 and I want to create 3 new arrays:
$recent - all events happened on the previous available day
$today - all events today
$upcoming - all events happening on the next available day
$today is easy:
$today = array();
for($i = 0; $i < count($events); ++$i) {
if($events[$i]['date'] == date("Y-m-d") {
array_push($today, $events[$i]['event']);
}
}
So, I will need $recent to contain event2 and event3, and $upcoming to contain event6 and event7.
The question is how to find the recent and the upcoming ones.
*Clarification:
I don't want all the events in $recent happened before today, but the events happened on the previous available day. So in this case only events happened on 2016-05-08
// Take all dates from source array
$dates = array_unique(array_map(function ($i) { return strtotime($i); } , array_column($events, 'date')));
sort($dates);
$today = strtotime('midnight');
// find previouse date. It will be 1970-1-1 if not present in array
$prev = #max(array_filter($dates, function($i) use($today) { return $i < $today; }));
// find туче date. It will be 1970-1-1 if not present in array
$next = #min(array_filter($dates, function($i) use($today) { return $i > $today; }));
$prev = date('Y-m-d', $prev);
$next = date('Y-m-d', $next);
// fill arrays
$recent = array();
$upcoming = array();
$today = array();
for($i = 0; $i < count($events); ++$i) {
if($events[$i]['date'] == date('Y-m-d')) {
array_push($today, $events[$i]['event']);
}
if($events[$i]['date'] == $prev) {
array_push($recent, $events[$i]['event']);
}
if($events[$i]['date'] == $next) {
array_push($upcoming , $events[$i]['event']);
}
}
Try with creating three (3) blank array, check the date is greater or less than today or not and push into array according to conditions.
$today = array();
$upcoming = array();
$recent = array();
$thisDay = date("Y-m-d");
$count = count($events);
$max = max(array_column($events, 'date'));
$min = min(array_column($events, 'date'));
for($i = 0; $i < $count; $i++){
if($events[$i]['date'] > $thisDay){
$max = ($max > $events[$i]['date']) ? $events[$i]['date'] : $max;
array_push($upcoming, $events[$i]['event']);
array_push($upcoming_dates, $events[$i]['date']);
}
elseif($events[$i]['date'] < $thisDay){
$min = ($min < $events[$i]['date']) ? $events[$i]['date'] : $min;
array_push($recent, $events[$i]['event']);
array_push($recent_dates, $events[$i]['date']);
}
else
array_push($today, $events[$i]['event']);
}
foreach($recent_dates as $key => $value){
if($value != $min)
unset($recent[$key]);
}
foreach($upcoming_dates as $key => $value){
if($value != $max)
unset($upcoming[$key]);
}
echo '<pre>';
print_r($today);
print_r($upcoming);
print_r($recent);
Result
Today:
Array
(
[0] => event4
[1] => event5
)
Upcoming:
Array
(
[0] => event6
[1] => event7
)
Recent:
Array
(
[1] => event2
[2] => event3
)
Note: You use push_array which is not any library function in PHP. For Re-index of recent and upcoming you can use array_values.
Another solution should be
$recent = array();
$upcoming = array();
$today = array();
$all_dates = array();
foreach ($events as $event):
array_push($all_dates, $event['date']);
endforeach;
if ($key = array_search('2016-05-10', $all_dates)) {
$prev_date = $all_dates[$key - 1];
}
for ($i = 0; $i < count($all_dates); $i++) {
if ($all_dates[$i] > $all_dates[$key]) {
$next_date = $all_dates[$i + 1];
break;
}
}
for ($i = 0; $i < count($events); ++$i) {
if ($events[$i]['date'] == date('Y-m-d')) {
array_push($today, $events[$i]['event']);
}
if ($events[$i]['date'] == $prev_date) {
array_push($recent, $events[$i]['event']);
}
if ($events[$i]['date'] == $next_date) {
array_push($upcoming, $events[$i]['event']);
}
}
echo '<pre>';
print_r($upcoming);
print_r($today);
print_r($recent);
Output will be
Array
(
[0] => event6
[1] => event7
)
Array
(
[0] => event4
[1] => event5
)
Array
(
[0] => event2
[1] => event3
)

Check date ranges (start and end date) for overlap

function checkDateOverlap($ranges) {
$res = $ranges[0];
$countRanges = count($ranges);
for ($i = 0; $i < $countRanges; $i++) {
$r1s = $res['start'];
$r1e = $res['end'];
$r2s = $ranges[$i]['start'];
$r2e = $ranges[$i]['end'];
if ($r1s >= $r2s && $r1s <= $r2e || $r1e >= $r2s && $r1e <= $r2e || $r2s >= $r1s && $r2s <= $r1e || $r2e >= $r1s && $r2e <= $r1e) {
$res = array(
'start' => $r1s > $r2s ? $r1s : $r2s,
'end' => $r1e < $r2e ? $r1e : $r2e
);
} else
return false;
}
return $res;
}
// example of returned dates that overlap
$ranges = array(
array('start' => '2014-01-01', 'end' => '2014-01-04'),
array('start' => '2014-01-05', 'end' => '2014-01-10'),
array('start' => '2014-01-04', 'end' => '2014-01-07')
);
//example of failure
$ranges2 = array(
array('start' => '2014-01-01', 'end' => '2014-01-04'),
array('start' => '2014-01-05', 'end' => '2014-01-10'),
array('start' => '2014-01-11', 'end' => '2014-01-17')
);
var_dump(checkDateOverlap($ranges));
The following is what I was attempting to check intersection of date ranges. In the array "ranges1" this example has overlapping dates. It should return the dates. In array $ranges2, this should pass as no intersecting dates.
Now the weird thing is the start and end date can be the exact same, so you could make an entry for just a single day. I've tried many things, and I'm stumped.
I believe there needs to be another for loop, but regardless I am not getting success.
Here was another go I had:
<?php
// pass your ranges to this method and if there is a common intersecion it will
// return it or false
function checkDateOverlap($ranges){
$res = $ranges[0];
$countRanges = count($ranges);
for ($i = 0; $i < count($countRanges); $i++) {
for($j = $i+1; $j < count($countRanges); $j++) {
$r1s = $res['start'];
$r1e = $res['end'];
$r2s = $ranges[$i]['start'];
$r2e = $ranges[$i]['end'];
if (($r1s >= $r2e && $r2s <= $r1e)) {
$res[] = array(
'start' => $r1s > $r2s ? $r1s : $r2s,
'end' => $r1e < $r2e ? $r1e : $r2e
);
} else
return false;
}
}
return $res;
}
// example
$ranges = array(
array('start' => '2014-01-04', 'end' => '2014-01-05'),
array('start' => '2014-01-06', 'end' => '2014-01-10'),
array('start' => '2014-01-11', 'end' => '2014-01-13')
);
echo "<pre>";
var_dump(checkDateOverlap($ranges));
echo "</pre>";
Any advice greatly appreciated.
$ranges = array(
array('start' => new DateTime('2014-01-01'), 'end' => new DateTime('2014-01-05')),
array('start' => new DateTime('2014-01-06'), 'end' => new DateTime('2014-01-06')),
array('start' => new DateTime('2014-01-07'), 'end' => new DateTime('2014-01-07')),
);
function intersects($lhs, $rhs) {
// Note that this function allows ranges that "touch",
// eg. one pair starts at the exact same time that the other ends.
// Adding less "or equal to" will allow same start date
return !($lhs['start'] > $rhs['end'] || $lhs['end'] < $rhs['start']);
}
function checkDates($ranges) {
// Comparison loop is of size n•log(n), not doing any redundant comparisons
for($i = 0; $i < sizeof($ranges); $i++) {
for($j = $i+1; $j < sizeof($ranges); $j++) {
if(intersects($ranges[$i], $ranges[$j])) {
echo "Date {$i} intersects with date {$j}\n";
}
}
}
}
checkDates($ranges);
I've attached my working code sample to hopefully help someone else in the future looking for the same solution. This will print the arrays that intersect.
If you use usort to first sort the dates, the work gets a lot easier. The following can be optimized a lot, but it is done step-by-step make it easier to understand.
//The date comparison function, sort on start and then on end
function cmp($a, $b)
{
if($a['start']<$b['start']) return -1;
if($a['start']>$b['start']) return 1;
if($a['end']<$b['end']) return -1;
if($a['end']>$b['end']) return 1;
return 0; // start=start and end=end
}
$ranges = array(
array('start' => '2014-01-01', 'end' => '2014-01-04'),
array('start' => '2014-01-05', 'end' => '2014-01-10'),
array('start' => '2014-01-04', 'end' => '2014-01-07')
);
usort($ranges, 'cmp'); // Sort the dates
$output = array();
for($i=0; $i<sizeof($ranges); $i++)
{
$endindex = $i; // The index containing the proper 'end' value
for($j=$i+1; $j<sizeof($ranges); $j++)
{
if($ranges[$endindex]['start'] == $ranges[$j]['start']) // Overlap
$endindex = $j;
elseif($ranges[$endindex]['end']>=$ranges[$j]['start']) // Overlap
$endindex = $j;
}
$output[] = array('start' => $ranges[$i]['start'], 'end' => $ranges[$endindex]['end']);
// Break the rules by hard-setting $i from the for loop - it works great in this case
$i = $endindex;
}
print_r($output);
It works for your example. If you have other rules that must be used, hopefully you can adjust this code.
Here are some remarks:
- You do not check the validity of the date formed by 'start' and 'end'.
- Why do you not convert the dates to timestamp ?
-> It's more easier and faster to compare integer value instead of string ?
Why do you not use PHP DateTime and DateInterval Objects ?
http://php.net/manual/en/book.datetime.php

Check if time interval does fall inside other time intervals

I want to determine if given interval doesn't fall inside other intervals (using 24-hour clock format), here is the example:
case1:
$startDate = '2021-04-05 08:05:00';
$endDate = '2021-04-05 10:05:00';
$intervals = [['startDate' => '2021-04-05 08:30:00', 'endDate' => '2021-04-05 11:05:00'], ['startDate' => '2021-04-05 12:30:00', 'endDate' => '2021-04-05 13:05:00']]
In this case we should set:
$flagCanSchedule = 0;
Because 2021-04-05 08:05:00 to 2021-04-05 10:05:00 falls between this interval:
'startDate' => '2021-04-05 08:30:00', 'endDate' => '2021-04-05
11:05:00'
But for this:
case 2:
$startDate = '2021-04-05 08:05:00';
$endDate = '2021-04-05 10:05:00';
$intervals = [['startDate' => '2021-04-05 10:05:00', 'endDate' => '2021-04-05 11:05:00'], ['startDate' => '2021-04-05 07:30:00', 'endDate' => '2021-04-05 08:05:00']]
In this case set:
$flagCanSchedule = 1;
Because we don't overlap any other interval, evan tho ('2021-04-05 08:05:00' == '2021-04-05 08:05:00').
I wanted to solve this using strtotime and transform the dates to unix format, but I'm not sure how to write my if statement.
$startDate = strtotime('2021-04-05 08:05:00');
$endDate = strtotime('2021-04-05 10:05:00');
foreach($intervals as $interval) {
if($startDate <= strtotime($interval['startDate']) && $endDate <=
strtotime($interval['endDate'])) {
$flagCanSchedule = 1;
} else {
$flagCanSchedule = 0;
}
}
You should add a break when a flagCanSchedule is found. Because, the next iterations overrides this value (from 1 to 0).
$intervals = [
['startDate' => '2021-04-05 10:05:00', 'endDate' => '2021-04-05 11:05:00'],
['startDate' => '2021-04-05 07:30:00', 'endDate' => '2021-04-05 08:05:00'],
];
$startDate = strtotime('2021-04-05 08:05:00');
$endDate = strtotime('2021-04-05 10:05:00');
foreach($intervals as $interval)
{
if ($startDate <= strtotime($interval['startDate']) &&
$endDate <= strtotime($interval['endDate']))
{
$flagCanSchedule = 1;
break; // << stop the test
}
else {
$flagCanSchedule = 0;
}
}
var_dump($flagCanSchedule); // int(1)
You also can remove the else statement by initializing the flag first.
$flagCanSchedule = 0;
foreach ($intervals as $interval)
{
if ($startDate <= strtotime($interval['startDate']) &&
$endDate <= strtotime($interval['endDate']))
{
$flagCanSchedule = 1;
break;
}
}
var_dump($flagCanSchedule); // int(1)

Categories