Manipulate the array based on start_time and end_time in PHP - php

i want output based on start_time and end_time.
Suppose there is parent array which has start_time and end_time has 6am and 8am. give it parent element 0.
3rd array has start_time and end_time has 6am and 6:30am this time falls between 1st arrays start_time and end_time so give it parent 1.
2nd array has start_time and end_time has 6am and 6:15am this time falls between 2nd array start_time and end_time so give it parent 2.
Note: there can be a lot of arrays and there is 24 hours time so anyone can be parent of anyother array. you can see in the example.
input array:
Array
(
[0] => Array
(
[id] => 1
[start_time] => 6am
[end_time] => 8am
)
[1] => Array
(
[id] => 2
[start_time] => 6am
[end_time] => 6:15am
)
[2] => Array
(
[id] => 3
[start_time] => 6am
[end_time] => 6:30am
)
)
Expected output:
Array
(
[0] => Array
(
[id] => 1
[start_time] => 6am
[end_time] => 8am
[parent] => 0
)
[1] => Array
(
[id] => 2
[start_time] => 6am
[end_time] => 6:15am
[parent] => 2 //increment this value of 3rd array parent by +1 because this time falls under 3rd array
)
[2] => Array
(
[id] => 3
[start_time] => 6am
[end_time] => 6:30am
[parent] => 1 //increment this value of 1st array parent by +1 because this time falls under 1st array
)
)
My code:
$count = count($input);
$output = array();
for ($i=0; $i < $count; $i++) {
$output[$i] = $input[$i];
$output[$i]['parent'] = $i;
for ($j=0; $j < $count; $j++) {
if ($i !== $j) {
if (checkOverlap($input[$i]['start_time'], $input[$i]['end_time'], $input[$j]['start_time'], $input[$j]['end_time'])) {
$output[$i]['parent'] = $j;
break;
}
}
}
}
function checkOverlap($start1, $end1, $start2, $end2) {
$start1 = strtotime($start1);
$end1 = strtotime($end1);
$start2 = strtotime($start2);
$end2 = strtotime($end2);
if ($start1 < $start2) {
if ($end1 > $start2 && $end1 < $end2) {
return true;
}
} else {
if ($start1 > $start2 && $start1 < $end2) {
return true;
}
}
return false;
}
I'm getting this output now which is wrong.
Array
(
[0] => Array
(
[id] => 1
[start_time] => 6am
[end_time] => 8am
[parent] => 0
)
[1] => Array
(
[id] => 2
[start_time] => 6am
[end_time] => 6:15am
[parent] => 1
)
[2] => Array
(
[id] => 3
[start_time] => 6am
[end_time] => 6:30am
[parent] => 2
)
)
it would very help for me if you can solve this.
see this event picture

Related

Fill missing array elements with zero values Codeigniter

I am fetching data from database which have dates that need to be sent to the view to create a chart. Some months might not have transactions which I need them to be autofilled with 0.
Model
function get_chart_data()
{
$this->db->order_by('month','asc');
$this->db->select('COUNT(*) as no_payments, SUM(amount) as total_payment_amount, YEAR(`date_paid`) AS year, MONTH(`date_paid`) AS month');
$this->db->group_by(array("year", "month"));
$this->db->where('tbl_payments.payment_type', "PAYMENT");
return $this->db->get('tbl_payments');
}
When I print_r in my controller the data is
Array ( [0] => stdClass Object ( [no_payments] => 1 [total_payment_amount] => 450 [year] => 2016 [month] => 1 ) [1] => stdClass Object ( [no_payments] => 5 [total_payment_amount] => 1162 [year] => 2016 [month] => 5 ) [2] => stdClass Object ( [no_payments] => 2 [total_payment_amount] => 1700 [year] => 2016 [month] => 6 ) )
How can I fill in the missing months and data with zero i.e the data to be
Array ( [0] => stdClass Object ( [no_payments] => 1 [total_payment_amount] => 450 [year] => 2016 [month] => 1 ) [1] => stdClass Object ( [no_payments] => 0 [total_payment_amount] => 0 [year] => 2016 [month] => 2 ) [2] => stdClass Object ( [no_payments] => 0 [total_payment_amount] => 0 [year] => 2016 [month] => 3 ) )
You could add them manually:
$months = array();
$query = $this->db->get('tbl_payments')->result();
foreach($query as $q)
{
$months[] = $q->month;
}
for($i = 1; $i <= 12; $i++)
{
if(!in_array($i, $months))
{
$new_data = new stdClass();
$new_data->no_payments = 0;
$new_data->total_payment_amount = 0;
$new_data->year = 2016;
$new_data->month = $i;
$query[] = $new_data;
}
}
That is asuming you will only need the filling months for current year. If you query other years, you may add that to the logic and include it in another loop.

Find duplicate values in a multidimensional array and create new multidimensional array that contains no dupes

I have the following array taken from a database:
Array
(
[0] => Array
(
[facility_name] => AFC Clayton Juniors
[day] => 15
[month] => Apr
[year] => 2016
[start_time] => 20
[end_time] => 21
)
[1] => Array
(
[facility_name] => AFC Clayton Juniors
[day] => 15
[month] => Apr
[year] => 2016
[start_time] => 22
[end_time] => 23
)
[2] => Array
(
[facility_name] => Chorlton Runners
[day] => 15
[month] => Apr
[year] => 2016
[start_time] => 10
[end_time] => 11
)
[3] => Array
(
[facility_name] => Chorlton Runners
[day] => 15
[month] => Apr
[year] => 2016
[start_time] => 19
[end_time] => 20
)
)
And I need it to be nested as follows::
Array
(
[0] => Array
(
[facility_name] => AFC Clayton Juniors
[dates] => Array
(
[date1] => Array
(
[date] => 15 Apr 2016
[timeslots] => Array
(
[timeslot1] => Array
(
[start_time] => 20
[end_time] => 21
)
[timeslot2] => Array
(
[start_time] => 22
[end_time] => 23
)
)
[date2] => 16 Apr 2016 //etc
)
)
[1] => Array
(
[facility_name] = Chorlton Runners
[dates] => Array //etc
)
)
To elaborate: I need to have NO duplicate names in my array, and the dates that exist for the same name to be entered as new keys to the dates array that match the same name, and the same thing for time slots. How can I do this?
For this solution let's say the array taken from the databse is named $facilities. The code would be:
$noDupes = array();
foreach ($facilities as $fac) {
$facilityIndex = -1; // The index of the facility name, -1 indicates it wasn't found.
$dateIndex = ''; // The index of the date string, an empty string indicates it wasn't found.
$timeslotIndex = ''; // The index of the timeslot, an empty string indicates it wasn't found.
$facDate = "{$fac['day']} {$fac['month']} {$fac['year']}"; // The date string (dd mmm aaaa)
foreach ($noDupes as $f => $facility) {
if ($fac['facility_name'] == $facility['facility_name']) {
// If the facility name was found we take the corresponding index (0, 1, 2, etc.).
$facilityIndex = $f;
foreach ($facility['dates'] as $d => $date) {
if ($facDate == $date['date']) {
// If the date string was found we take the corresponding index (date1, date2, date3, etc.).
$dateIndex = $d;
foreach ($date['timeslots'] as $t => $timeslot) {
if ($fac['start_time'] == $timeslot['start_time'] && $fac['end_time'] == $timeslot['end_time']) {
// If the timeslot was found we take the corresponding index (timeslot1, timeslot2, timeslot3, etc.).
$timeslotIndex = $t;
break; // end timeslot loop
}
}
break; // end date loop
}
}
break; // end facility loop
}
}
if ($facilityIndex == -1) {
// Take the new index for the date and timeslot if-statements
$facilityIndex = count($noDupes);
$noDupes[] = array(
'facility_name' => $fac['facility_name'],
'dates' => array()
);
}
if ($dateIndex == '') {
// Calculate the new index for the date (date1, date2, etc.)
$dateNum = count($noDupes[$facilityIndex]['dates']) + 1;
$dateIndex = "date{$dateNum}";
$noDupes[$facilityIndex]['dates'][$dateIndex] = array(
'date' => $facDate,
'timeslots' => array()
);
}
if ($timeslotIndex == '') {
// Calculate the new index for the timeslot (timeslot1, timeslot2, etc.)
$timeslotNum = count($noDupes[$facilityIndex]['dates'][$dateIndex]['timeslots']) + 1;
$timeslotIndex = "timeslot{$timeslotNum}";
$noDupes[$facilityIndex]['dates'][$dateIndex]['timeslots'][$timeslotIndex] = array(
'start_time' => $fac['start_time'],
'end_time' => $fac['end_time']
);
}
}
Using JSON array will make your task very easy, and is supported in PHP

How to get max time form array elements

I want to get highest time from time_array.In below code I manually gave timings it is wrong.
time_array is like this,
Array (
[0] => Array (
[1] => Array ( [date] => 2016-04-09 [time] => 0900 [after_time] => 1100
[2] => Array ( [date] => 2016-04-10 [time] => 1100 [after_time] => 1300
[3] => Array ( [date] => 2016-04-11 [time] => 1300 [after_time] => 1500
)
)
my code,
<?php
foreach ($time_array AS $row) {
for($j=$start; $j < $limit ; $j++){
if($row[$start]['time']=='1300' && $row[$start]['after_time']=='1500' ){
//code
}else{
//code
}
}
}
?>
If you are using foreach
check this once
foreach ($time_array as $arr){
$ar = array_column($arr, 'time');
}
echo max($ar);

Generate an array using DateInterval and DatePeriod for shifts

I'm using DateInterval and DatePeriod to generate shifts in a medical application
$begin = new DateTime('2012-08-01 08:00');
$end = new DateTime('2012-08-01 12:00');
$interval = new DateInterval('PT45M');
$daterange = new DatePeriod($begin, $interval ,$end);
Those functions allow me to generate the following array
Array
(
[0] => 08:00
[1] => 08:45
[2] => 09:30
[3] => 10:15
[4] => 11:00
[5] => 11:45
)
Which functions and how could I do so the final array gets completed and chunked as this?
Array
(
[0] => Array
(
[0] => 08:00
[1] => 08:45
)
[1] => Array
(
[0] => 08:45
[1] => 09:30
)
[2] => Array
(
[0] => 09:30
[1] => 10:15
)
[3] => Array
(
[0] => 10:15
[1] => 11:00
)
[4] => Array
(
[0] => 11:00
[1] => 11:45
)
)
Thanks
$previous = null;
$dates = array();
foreach ($period as $dt) {
$current = $dt->format("H:i");
if (!empty($previous)) {
$show = new DateTime($current);
$dates[] = array($previous, $show->format('H:i'));
}
$previous = $current;
}
After retrieve your array using DateTime function. Just Plug n Play with the code. :)
$retrieveArray = array('08:00','08:45','09:30','10:15','11:00','11:45'); // Sample Array, Assumed mentioned in Question.
$final = array();
for ($i=0; $i < count($retrieveArray)-1; $i++) {
$j = $i+1;
$final[$i] = array($retrieveArray[$i], $retrieveArray[$j]);
}
Use var_dump($final); to check array result.
Desired Output
Array
(
[0] => Array
(
[0] => 08:00
[1] => 08:45
)
[1] => Array
(
[0] => 08:45
[1] => 09:30
)
[2] => Array
(
[0] => 09:30
[1] => 10:15
)
[3] => Array
(
[0] => 10:15
[1] => 11:00
)
[4] => Array
(
[0] => 11:00
[1] => 11:45
)
)
Edit:
To Add Last Shift
#jhon is right. It skips the last boundary value if it matches exactly the length of the interval.
As you need it, I suggest to ADD +1 min to your end time. It's a tweak/fix but server the purpose.
$begin = new DateTime('2012-08-01 08:00');
$end = new DateTime('2012-08-01 10:00');
$end = $end->modify( '+1 minute' ); // Tweak, to add last shift value.
$interval = new DateInterval('PT30M');
$daterange = new DatePeriod($begin, $interval ,$end);
To Check Output
foreach ( $daterange as $dt ){
echo '<pre>';
echo $dt->format( "H:i" );
echo '</pre>';
}
It is including last boundary value if it matches exactly the length of the interval.

Array montlhy reporting but not from 1st of month

I have a large array of booking dates and amount, like so :
Array
(
[0] => Array
(
[date] => 2014-04-04
[total] => 30.00
)
[1] => Array
(
[date] => 2014-04-05
[total] => 47.00
)
[9998] => Array
(
[date] => 2014-08-21
[total] => 52.00
)
... ++ a lot of dates associated to numbers.
and process it to get monthly reports :
$months = array();
foreach($myarray as $k=>$v) {
list($y,$m) = explode("-",$v['date']);
$months[$y."-".$m][] = $v['total'];
}
which gives me a nice array :
Array
(
[2014-04] => Array <-- Every amount made in April
(
[0] => 30.00
[1] => 47.00
[2] => 47.00
...
)
[2014-05] => Array <-- Every amount made in May
(
[0] => 68.00
[1] => 42.00
....
)...
However I'm trying to find a way the same thing but starting from a specific day, say 5 for example, in order to get (dates labelled for clarity):
Array
(
[from January 5 to February 4] => Array
(
[0] => 30.00
[1] => 47.00
[2] => 47.00
)
[from February 5 to March 4] => Array
(
[0] => 30.00
[1] => 47.00
[2] => 47.00
)...
So every amount made each month, but starting from the 5th of each month.
Something like this should work. I hate saying should, but I don't have the data to test with. Let me know if anything's wrong:
$months = array();
foreach($months as $k => $v) {
list($y, $m, $d) = explode("-", $v['date']);
if($d < 5) {
if($m == 1) {
$y--;
$m = 12;
} else {
$m--;
}
}
$months[$y . "-" . $m][] = $v['total'];
}

Categories