find the closest next date from the array in php - php

I have this array and want to find the next closest date for 02/21/2019 and set and as next date on my page, any help or idea will be appreciated
Array
(
[0] => 2019-02-17
[1] => 02/09/2019
[2] => 02/23/2019
[3] => 02/18/2019
[4] => 02/25/2019
[5] => 03/04/2019
[6] => 03/11/2019
[7] => 03/18/2019
[8] => 03/25/2019
[9] => 04/01/2019
[10] => 04/08/2019
)

This is the solution I used for finding the closest next date for my program and it's working.
$date = '02/21/2019';
$allDates= array
(
'2019-02-17',
'02/09/2019',
'02/23/2019',
'02/18/2019',
'02/25/2019',
'03/04/2019',
'03/11/2019',
'03/18/2019',
'03/25/2019',
'04/01/2019',
'04/08/2019',
);
function date_sort($a, $b) {
return strtotime($a) - strtotime($b);
}
usort($allDates, "date_sort");
foreach ($allDates as $count => $dateSingle) {
if (strtotime($date) < strtotime($dateSingle)) {
$nextDate = date('m-d', strtotime($dateSingle));
break;
}
}
echo $nextDate;

Please see this solution. Hope this help
<?php
$search = strtotime('02/21/2019');
$arrValues = array
(
'2019-02-17',
'02/09/2019',
'02/23/2019',
'02/18/2019',
'02/25/2019',
'03/04/2019',
'03/11/2019',
'03/18/2019',
'03/25/2019',
'04/01/2019',
'04/08/2019',
);
foreach($arrValues as $val) {
$newArr[] = strtotime($val);
}
function getClosest($search, $arr) {
$closest = null;
foreach ($arr as $item) {
if($search <= $item) {
if ($closest === null || abs($search - $closest) > abs($item - $search)) {
$closest = $item;
}
}
}
return $closest;
}
$closest = getClosest($search, $newArr);
echo date('Y-m-d', $closest);
?>

Convert date to unix time and compare numbers. I didn’t test it, just an idea...
Sort array elements in order then pick next element closest to you date (element)

I am assuming you can fix the format of array and make it same
$dates = array
(
'0'=> "2013-02-18",
'1'=> "2013-02-12",
'2'=> "2013-02-05",
'3'=> "2013-01-29",
'4'=> "2013-01-27"
);
$current = date("Y-m-d");
//$count = 0;
foreach($dates as $day)
{
//$interval[$count] = abs(strtotime($date) - strtotime($day));
$interval[] = abs(strtotime($current) - strtotime($day));
//$count++;
}
asort($interval);
$closest = key($interval);
echo trim($datarray[$closest]);

Related

How can I separate from and to dates from dates array?

I have an array, which has only one month dates.
$dates =array (
'2018-10-15',
'2018-10-16',
'2018-10-17',
'2018-10-13',
'2018-10-19',
'2018-10-10',
'2018-10-11',
'2018-10-12',
'2018-10-22',
'2018-10-23',
'2018-10-29',
);
And script below
usort($dates,function($a,$b){
return strtotime($a) - strtotime($b);
});
$consecutive_added_set = [];
$consecutive_array = [];
$temp = [];
$temp[] = date('Y-m-d',strtotime($dates[0]));
for($i=1;$i<count($dates);++$i){
if(strtotime($dates[$i]) - strtotime($dates[$i - 1]) === 86400){ // 1 day gap(86400 seconds)
$temp[] = date('Y-m-d',strtotime($dates[$i]));
$consecutive_added_set[$dates[$i-1]] = true;
$consecutive_added_set[$dates[$i]] = true;
}else{
if(count($temp) > 1){
$consecutive_array[] = $temp;
}
$temp = [];
$temp[] = date('Y-m-d',strtotime($dates[$i]));
}
}
if(count($temp) > 1){ // the last consecutiveness match of dates as well(corner case)
$consecutive_array[] = $temp;
}
$conseq[] = []; // reset the array structure
$conseq['consecutive'] = $consecutive_array;
$conseq['consecutive_count'] = count($consecutive_array);
$conseq['non_consecutive'] = [];
foreach($dates as $current_date){
if(!isset($consecutive_added_set[$current_date])){ // skip all dates which were d for consecutiveness
$conseq['non_consecutive'][] = date('Y-m-d',strtotime($current_date));
}
}
Which is sorting and separating consecutive and non-consective dates. Currently in consecutive array it is showing all dates by group. But I just would like to show from and to dates. Here is output of above script
Array
(
[0] => Array
(
)
[consecutive] => Array
(
[0] => Array
(
[0] => 2018-10-10
[1] => 2018-10-11
[2] => 2018-10-12
[3] => 2018-10-13
)
[1] => Array
(
[0] => 2018-10-15
[1] => 2018-10-16
[2] => 2018-10-17
)
[2] => Array
(
[0] => 2018-10-22
[1] => 2018-10-23
)
)
[consecutive_count] => 3
[non_consecutive] => Array
(
[0] => 2018-10-19
[1] => 2018-10-29
)
)
My desired output
[consecutive] => Array
(
['dates1'] => Array
(
[0] => 2018-10-10
[3] => 2018-10-13
)
['dates2'] => Array
(
[0] => 2018-10-15
[2] => 2018-10-17
)
['dates3'] => Array
(
[0] => 2018-10-22
[1] => 2018-10-23
)
)
I have tried a lot to do it.
A quick workaround would be to get the first and last item in the array.
$consecutive_array = array_map(function($e){
if(!is_array($e)){
return $e;
}
$last = end($e);
return [reset($e), $last];
}, $consecutive_array);
Or as suggested in the comments use min() max() functions.
$consecutive_array = array_map(function($e){
if(!is_array($e)){
return $e;
}
return [min($e), max($e)];
}, $consecutive_array);
Important: don't rely on strtodate of a day being exactly 86400 seconds less than the strtodate of the next day - depending on the locale of the server, there will be daylight saving, which can mess this up!
In cases like this, I tend to compare strtodate('+1 day',$timestampOfDay1) to strtodate($timestampOfDay2) - this will include daylight saving.
Here's how I would do it:
//the dates
$dates =array (
'2018-10-15',
'2018-10-16',
'2018-10-17',
'2018-10-13',
'2018-10-19',
'2018-10-10',
'2018-10-11',
'2018-10-12',
'2018-10-22',
'2018-10-23',
'2018-10-29',
);
//call the function
$result = getConsecutive($dates);
//output
var_dump($result);
function getConsecutive($dates) {
sort($dates);
$result = [
'consecutive' => [],
'consecutive_count'=>0,
'non_consecutive' => []
];
$currentStart = null;
$currentTimestamp = null;
for ($i=0; $i<count($dates); $i++) {
$timestamp = strtotime($dates[$i]);
if ($currentStart == null) {
//first timestamp - set it as start & current
$currentStart = $timestamp;
$currentTimestamp = $timestamp;
} else if (strtotime('+1 day',$currentTimestamp) == $timestamp) {
//consecutive - keep waiting for a non-consecutive
$currentTimestamp = $timestamp;
} else {
if ($currentTimestamp == $currentStart) {
//we just got one
$result['non_consecutive'][] = date('Y-m-d',$currentTimestamp);
} else {
//we just got more then one, so they were consecutive
$result['consecutive']['dates'.(count($result['consecutive'])+1)] = [
date('Y-m-d',$currentStart),
date('Y-m-d',$currentTimestamp)
];
}
$currentStart = $timestamp;
$currentTimestamp = $timestamp;
}
}
//process the last timestamp
if ($currentTimestamp == $currentStart) {
//we just got one
$result['non_consecutive'][] = date('Y-m-d',$currentTimestamp);
} else {
//we just got more then one, so they were consecutive
$result['consecutive']['dates'.(count($result['consecutive'])+1)] = [
date('Y-m-d',$currentStart),
date('Y-m-d',$currentTimestamp)
];
}
$result['consecutive_count'] = count($result['consecutive']);
return $result;
}

PHP check if variable is smaller than previous item in array

I need a way to check if there are events that overlap each other. So I made an array with the start and end hour of every event. It looks like this:
Array
(
[0] => Array
(
[start] => 0930
[end] => 1200
)
[1] => Array
(
[start] => 1000
[end] => 1230
)
[2] => Array
(
[start] => 1300
[end] => 1530
)
)
This is what I've tried to check if there are events that overlap:
if ( $orders->have_posts() ):
while ($orders->have_posts()) : $orders->the_post();
foreach($order as $o){
$start = $o['start'];
$end = $o['end'];
$attractieID = $o['attractie']->ID;
foreach($order as $key => $attractieID){
$slots[] = array('start' => $start, 'end' => $end);
if($start < $end){
//overlap
}else{
//no overlap
}
}
}
endwhile;
endif;
But this will always give true since I am checking the start and end date of the same item in my array.
I need to way to compare the start value of the current array item and the end value of the previous array item
Anyone knows if this is even possible?
Many thanks in advance!
Start looping at index 1, and compare the start time of the current event with the end of the event with index-1.
$count = count($order);
for ($i = 1; $i < $count; $i++) {
if ($order[$i]['start'] < $order[$i-1]['end']) {
// overlap
} else {
// no overlap
}
}
If you want to do this while also copying from $order to slots, you can use a variable to hold the end time from the previous iteration.
$prevEnd = null;
foreach($order as $o){
$start = $o['start'];
$end = $o['end'];
$attractieID = $o['attractie']->ID;
$slots[] = array('start' => $start, 'end' => $end);
if($prevEnd !== null && $start < $prevEnd){
//overlap
}else{
//no overlap
}
$prevEnd = $end;
}
DEMO
Try this code, with a for loop instead of foreach:
for($i=0;$i<count($order);i++){
$slots[] = array('start' => $start, 'end' => $end);
if($order[$i+1]){
if($order[$i]['start'] < $order[$i+1]['end']{
//overklap
}else{
//no overlap
}
}
Just use a normal for loop. And, to be sure everything is right, sort the array before checking it (if you are sure it is gona be sorted, you can skip that part)
$sortedOrders = usort($order, function($a, $b)
{
$aStart = $a['start'];
$bStart = $b['start'];
return ($a < $b) ? -1 : 1;
});
$count = count($sortedOrders);
for($i = 1; $i < $count; $i++)
{
if($sortedOrders[$i - 1]['end'] > $sortedOrders[$i]['start'])
{
// Handle overlap
}
}

Adding elements to an Array using a special loop for iteration

Supposing I have an Array with x elements. I would like to loop through this Array in "tens" and add a run-Time variable. This means that each set of 10 Arrays will have a unique run-time. I am using the code below:
$time = '00:00:00';
$k = 0;
for ($i = 0; $i < count($agnt_arr); $i+=10) {
$temp = strtotime("+$k minutes", strtotime($time));
$runTime = date('H:i', $temp);
array_push($agnt_arr[$i], $runTime);
$k+=4;
}
Where $agnt_arr is an Array with the following structure :
Array
(
[0] => Array
(
[name] => User.One
[email] => User.One#mail.com
)
[1] => Array
(
[name] => User.Two
[email] => User.Two#mail.com
)
[2] => Array
(
[name] => User.Three
[email] => User.Three#mail.com
)
)
The problem I'm having is the run times are only added to the 10th element which is expected But I would like elements 0-9 to have the same run time and 10-20 etc. How would I achieve something like this??
Probably easier like this always adding runtime but updating it for each 10:
$time = '00:00:00';
foreach($agent_arr as $key => $value) {
if($key % 10 === 0) {
$temp = strtotime("+$k minutes", strtotime($time));
$runTime = date('H:i', $temp);
}
$agent_arr[$key]['runtime'] = $runTime;
}
Here's my overcomplicated solution(and probably unnecessary):
$new_array = array();
foreach(array_chunk($array, 10 /* Your leap number would go here */) as $k => $v)
{
array_walk($v, function($value, $key) use (&$new_array){
$value['time'] = $time;
$new_array[] = $value;
});
}

Adding missing dates for 1 week back from now

I am trying to add the missing dates to this array for 1 week back from now.
This is an example array I have;
Array
(
[0] => Array
(
[date] => 2013-11-25
[members] => 2
)
[1] => Array
(
[date] => 2013-11-27
[members] => 1
)
)
This could have any dates in. I tried things like this, but I can see logically It doesn't work, but I cannot figure out a way.
$date_range = array();
$temp = array();
for ($i=0; $i<7; $i++)
{
$date = date("Y-m-d", strtotime($i." days ago"));
foreach($new_members as $members) {
if(!in_array($date, $members)) {
$temp['date'] = $date;
$temp['members'] = 0;
$new_members[] = array_merge($temp);
}
}
}
Solution provided by Dainis doesn't work for me, it's messing up the members and date.
Here is my solution:
<?php
$new_members = array ( array("date"=>"2013-11-25", "members" => 2), array("date"=>"2013-11-27", "members" => 2));
for ($i=0; $i<7; $i++)
{
$date = date("Y-m-d", strtotime($i." days ago"));
$found = false;
foreach($new_members as $members) {
if(array_search($date, $members) !== false) {
$found = true;
}
}
if(!$found) {
$new_members[] = array ("date" => $date, "members" => 0);
}
}
foreach($new_members as $nm) {
var_dump($nm);
}
?>
Instead of:
$temp['date'] = $date;
$temp['members'] = 0;
$new_members[] = array_merge($temp);
just do it like this:
$new_members[$i]['date'] = $date;
if ( !$new_members[$i]['members'] ) $new_members[$i]['members'] = 0;
After that you can sort it after ['date'] value and get a nice looking array.

PHP Multidimensional Array problem

iam trying to build a multidimensional array.
public function saveRateTemplateData($RateTemplateInfo)
{
$RateTemplateID = $RateTemplateInfo['id'];
$Zones = $RateTemplateInfo['premium_zones'];
//$ZoneZipCodeIDs[] = array();
for ($n = 1; $n <= $RateTemplateInfo['premium_zones']; $n++) {
$ZoneNum = 'zone' . $n;
$ZipCodeArray = explode(",",$_POST[$ZoneNum]);
$ZipCodeIDs=array();
foreach ($ZipCodeArray as $v) {
$v = intval(trim($v));
if (strlen($v) == 5) {
array_push($ZipCodeIDs, $this->addZipCode($v));
} else {
echo "it isnt 5";
}
}
}
}
so what iam trying to do is make an array of an array. so this is how its supposed to look
Array
(
[1] => Array
(
[0] => 34
[1] => 31
[2] => 23
)
[2] => Array
(
[0] => 18
[1] => 4
[2] => 35
[3] => 1
)
)
i have tried numerous ways it doesnt work
basically i want it in this format VarName[ZoneNumbers][ZipCodeID]
so i can loop through it later on. so i can print like this $VarName[$n] then a array of all zipcodeID will print for Zone Number 1 in this case it will print 34,31,23
public function saveRateTemplateData($RateTemplateInfo)
{
$RateTemplateID = $RateTemplateInfo['id'];
$zones = array(); // you weren't using this so I'll use it to hold the data
for ($n = 1; $n <= $RateTemplateInfo['premium_zones']; $n++) {
$ZoneNum = 'zone' . $n;
// create an array under the zone number for holding the IDs
$zones[$n] = array();
$ZipCodeArray = explode(",",$_POST[$ZoneNum]);
foreach ($ZipCodeArray as $v) {
$v = (int) trim($v);
if (strlen($v) == 5) {
$zones[$n][] = $this->addZipCode($v);
} else {
// use exceptions for exceptional circumstances
throw new RuntimeException(sprintf('Invalid zone ID "%s"', $v));
}
}
}
return $zones;
}

Categories