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.
Related
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;
}
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]);
I want to group array values
my array looks like below with 30 mins time interval
$arr = ["00:00","00:30","01:00","01:30","02:00","02:30","03:00","04:30","05:00","05:30"];
i want the output like
Array ( [0] => Array ( [0] => 00:00 [1] => 03:00 ),[1]=> Array ( [0] => 04:30 [1] => 05:30 )) ;
Here is my code for achieving the result
$output = array();
$start = $arr[0];
for($i=1; $i<count($arr); $i++) {
if($i == count($arr)-1) {
$interval = array($start,$arr[$i]);
array_push($output,$interval);
break;
}
if((int)($arr[$i]) - (int)($arr[$i-1]) > 1) {
$interval = array($start,$arr[$i-1]);
array_push($output,$interval);
$start = $arr[$i];
}
}
print_r($output);
but i got the result looks like
Array ( [0] => Array ( [0] => 00:00 [1] => 05:30 ) )
Thanks
$times = ["00:00","00:30","01:00","01:30","02:00","02:30","03:00","04:30","05:00","05:30"];
$result = array();
$index = 0;
for ($i=0; $i < count($times); $i++){
if($i == 0){
$result[$index][] = $times[$i];
}elseif($i == count($times)-1){
$result[$index][] = $times[$i];
}else{
if((h2m($times[$i])-h2m($times[$i-1])) > 30){
$result[$index][] = $times[$i-1];
$index++;
$result[$index][] = $times[$i];
}
}
}
var_dump($result);
FUNCTION h2m($hours) {
$t = EXPLODE(":", $hours);
$h = $t[0];
IF (ISSET($t[1])) {
$m = $t[1];
} ELSE {
$m = "00";
}
$mm = ($h * 60) + $t[1];
RETURN $mm;
}
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;
});
}
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;
}