Generate an array using DateInterval and DatePeriod for shifts - php

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.

Related

Manipulate the array based on start_time and end_time in 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

PHP compare previous values and store latest value in array

Following is my code to bring all the latest dates in a month from dates array
$dates = Array
(
"2017/03/05",
"2017/03/06",
"2017/04/01",
"2017/04/16",
"2017/06/16",
"2017/06/19",
"2017/07/07",
"2017/08/19",
);
$curr_val = '';
$years = Array();
$months = Array();
foreach($dates as $d) {
list($y,$m) = explode("/",$d);
$years[$y][] = $d;
if ($m != $curr_val){
$months[$y."/".$m][] = $d;
$curr_val = $m ;
}
}
$years = array_values($years);
$months = array_values($months);
print_r($months);
Above code is printing values of first occurance date in a month. But i want the latest date from month.
Above code gives following output
Array ( [0] => Array ( [0] => 2017/03/05 ) [1] => Array ( [0] => 2017/04/01 ) [2] => Array ( [0] => 2017/06/16 ) [3] => Array ( [0] => 2017/07/07 ) [4] => Array ( [0] => 2017/08/19 ) )
But expected code is
Array ( [0] => Array ( [0] => 2017/03/06 ) [1] => Array ( [0] => 2017/04/16 ) [2] => Array ( [0] => 2017/06/19 ) [3] => Array ( [0] => 2017/07/07 ) [4] => Array ( [0] => 2017/08/19 ) )
Instead of printing first date in month, i want last date of month to be printed. how can i get that??
Your code could be reduced a lot. Here's what I could do:
$dates = Array
(
"2017/03/05",
"2017/03/06",
"2017/04/01",
"2017/04/16",
"2017/06/16",
"2017/06/19",
"2017/07/07",
"2017/08/19",
);
$array = [];
foreach($dates as $d) {
$date = \DateTime::createFromFormat('Y/m/d' , $d);
if (
!isset($array[$date->format('Y')][$date->format('m')])
|| $array[$date->format('Y')][$date->format('m')] < $date
) {
$array[$date->format('Y')][$date->format('m')] = $date;
}
}
print_r($array);
It's a simple logic that will check if the value is higher inside the same year/month and replace if it is.
Result:
Array (
[2017] => Array
(
[03] => DateTime Object
(
[date] => 2017-03-06 22:18:42.000000
[timezone_type] => 3
[timezone] => Europe/Amsterdam
)
[04] => DateTime Object
(
[date] => 2017-04-16 22:18:42.000000
[timezone_type] => 3
[timezone] => Europe/Amsterdam
)
[06] => DateTime Object
(
[date] => 2017-06-19 22:18:42.000000
[timezone_type] => 3
[timezone] => Europe/Amsterdam
)
[07] => DateTime Object
(
[date] => 2017-07-07 22:18:42.000000
[timezone_type] => 3
[timezone] => Europe/Amsterdam
)
[08] => DateTime Object
(
[date] => 2017-08-19 22:18:42.000000
[timezone_type] => 3
[timezone] => Europe/Amsterdam
)
)
)
Like this:
foreach($dates as $d) {
list($y,$m) = explode("/",$d);
$years[$y][] = $d;
$months[$y."/".$m] = [$d];
}
Don't worry about keeping track of the current value. Just keep overwriting $months[$y."/".$m] as you go, and you'll end up with the last date for each month.
If you want to get the most recent date from each month, rather than just the last one in the input array, make sure $dates is sorted before you start the loop. Since they're in year/month/day format, a simple sort($dates); should work. (In the case of your example, $dates is already sorted so this won't make any difference.)
This seems simplest to me:
Code: (Demo)
$dates[
"2017/03/05",
"2017/03/06",
"2017/04/01",
"2017/04/16",
"2017/06/16",
"2017/06/19",
"2017/07/07",
"2017/08/19"
];
foreach($dates as $d){
$result[substr($d,0,7)]=$d; // extract unique key from values
}
$result=array_values($result); // reindex array
var_export($result);
Output:
array (
0 => '2017/03/06',
1 => '2017/04/16',
2 => '2017/06/19',
3 => '2017/07/07',
4 => '2017/08/19',
)

How to print array data following current date

I have an array like the following:
$f= array("Sunday", "Monday","Tuesday","Wednesday", "Thursday","Friday", "Saturday");
I have run a foreach loop for $f and print date. Result is:
Array ( [0] => Sunday [1] => Monday [2] => Tuesday [3] => Wednesday [4] => Thursday [5] => Friday [6] => Saturday )
but I want if it is Wednesday today, then the output will be:
Array ( [0] => Wednesday [1] => Thursday [2] => Friday [3] => Saturday [4] => Sunday [5] => Monday [6] => Tuesday )
Here is my code:
$f= array("Sunday", "Monday","Tuesday","Wednesday", "Thursday","Friday", "Saturday");
foreach ($f as $value) {
if($value == date('l')){
$date[] = $value;
}
}
print_r($date);
it return me the following result:
Array ( [0] => Thursday [1] => Thursday [2] => Thursday [3] => Thursday [4] => Thursday [5] => Thursday [6] => Thursday )
You can do it by native php functions:
$i = array_search(date('l'), $f);
$date = array_merge(array_splice($f, $i), $f);
array_search finds today item in the array, array_splice removes tail of the array and returns it, array_merge combines that arrays in the proper order
demo on eval.in

PHP Date difference , save each day between in array

I have an array which each element contains a startdate and enddate formated in 'dd.mm.yy'.
Array
(
[0] =
(
[date_start] = 23.07.2014
[date_end] = 02.08.2014
)
)
Now i need to build an array that will contain every day between date_start and date_end to validate them later.
Now my question is how can i calculate every day between those dates and save it to an array ?
IF YOU JUST WANT DATE DIFFERENCE
<?php
$arr=array
(
array
(
'date_start' =>'23.07.2014',
'date_end' =>'02.08.2014'
),
array
(
'date_start' =>'15.07.2014',
'date_end' =>'02.08.2014'
)
);
foreach($arr as $key=>$val){
$diff=strtotime($val['date_end'])-strtotime($val['date_start']);
$new_arr[]=array(
'day_start'=>$val['date_start'],
'day_end'=>$val['date_end'],
'difference'=>$diff/(24*60*60)-1
);
}
print_r($new_arr);
?>
OUTPUT
Array
(
[0] => Array
(
[day_start] => 23.07.2014
[day_end] => 02.08.2014
[difference] => 9
)
[1] => Array
(
[day_start] => 15.07.2014
[day_end] => 02.08.2014
[difference] => 17
)
)
IF YOU WANT ALL DATE BETWEEN ARRAYS
<?php
$arr=array
(
array
(
'date_start' =>'23.07.2014',
'date_end' =>'02.08.2014'
),
array
(
'date_start' =>'15.07.2014',
'date_end' =>'02.08.2014'
)
);
foreach($arr as $key=>$val){
$diff=strtotime($val['date_end'])-strtotime($val['date_start']);
$day_diff=$diff/(24*60*60);
$alldiff=array();
for($i=1;$i<=$day_diff-1;$i++){
$alldiff[]=date('d.m.Y',(strtotime($val['date_start'])+$i*24*60*60));
}
$new_arr[]=array(
'day_start'=>$val['date_start'],
'day_end'=>$val['date_end'],
'difference'=>$alldiff
);
}
echo "<pre>";
print_r($new_arr);
?>
OUTPUT
Array
(
[0] => Array
(
[day_start] => 23.07.2014
[day_end] => 02.08.2014
[difference] => Array
(
[0] => 24.07.2014
[1] => 25.07.2014
[2] => 26.07.2014
[3] => 27.07.2014
[4] => 28.07.2014
[5] => 29.07.2014
[6] => 30.07.2014
[7] => 31.07.2014
[8] => 01.08.2014
)
)
[1] => Array
(
[day_start] => 15.07.2014
[day_end] => 02.08.2014
[difference] => Array
(
[0] => 16.07.2014
[1] => 17.07.2014
[2] => 18.07.2014
[3] => 19.07.2014
[4] => 20.07.2014
[5] => 21.07.2014
[6] => 22.07.2014
[7] => 23.07.2014
[8] => 24.07.2014
[9] => 25.07.2014
[10] => 26.07.2014
[11] => 27.07.2014
[12] => 28.07.2014
[13] => 29.07.2014
[14] => 30.07.2014
[15] => 31.07.2014
[16] => 01.08.2014
)
)
)
This should work:
$startDate = new DateTime('2014-05-01');
$endDate = new DateTime('2014-06-02');
// calculate diff
$diff = $startDate->diff($endDate);
$daysDiff = $diff->days;
for ($i = 0; $i < $daysDiff; $i++) {
// clone so the original date will not be changed
$currentDate = clone $startDate;
$currentDate->modify('+'.$i.' days');
echo $currentDate->format('Y-m-d H:i:s')."\n";
}
Now you only have to make this for every array entry and save it to an array
Why don't you convert dates into timestamp, then you loop from the timestamp_start until timestamp_end , by day amount of seconds, then you convert each steps into a new date to check later.
Something like this?
// Convert start and end dates to unix timestamp
$start = strptime($date_array[0]['date_start'], '%d.%m.%Y');
$end = strptime($date_array[0]['date_end'], '%d.%m.%Y');
$dates = array();
while ($start < $end){
$dates[] = date('d.m.Y', $start);
$start += 86400 // One day equals 86400 seconds
}
Try this as it is working for me
function getDates($startTime, $endTime) {
$day = 86400;
$format = 'd.m.Y';
$startTime = strtotime($startTime);
$endTime = strtotime($endTime);
$numDays = round(($endTime - $startTime) / $day);
$days = array();
for ($i = 1; $i < $numDays; $i++) {
$days[] = date($format, ($startTime + ($i * $day)));
}
return $days;
}
$days = getDates('23.07.2014', '02.08.2014');

Generate interval date from array

I have two dates (start and end), for example:
$date['start'] = '2012-07-11';
$date['end'] = '2012-07-13';
i would like generate -4 and +4 days interval for this. So i would like receive for example array with:
$date['start'] = '2012-07-07';
$date['end'] = '2012-07-09';
$date['start'] = '2012-07-08';
$date['end'] = '2012-07-10';
$date['start'] = '2012-07-09';
$date['end'] = '2012-07-11';
$date['start'] = '2012-07-10';
$date['end'] = '2012-07-12';
$date['start'] = '2012-07-11';
$date['end'] = '2012-07-13';
$date['start'] = '2012-07-12';
$date['end'] = '2012-07-14';
$date['start'] = '2012-07-13';
$date['end'] = '2012-07-15';
$date['start'] = '2012-07-14';
$date['end'] = '2012-07-16';
$date['start'] = '2012-07-15';
$date['end'] = '2012-07-17';
How is the best way for this?
This code does the trick:
$date['start'] = '2012-07-11';
$date['end'] = '2012-07-13';
$dates=array();
for ($i=-4; $i<=4; $i++){
$startDate=strtotime($date['start'] );
$endDate=strtotime($date['end'] );
$startDate=$startDate+($i*60*60*24); //60*60*24 equal to one day
$endDate=$endDate+($i*60*60*24);
array_push($dates, array('start'=>date('Y-m-d', $startDate), 'end'=> date('Y-m-d',$endDate)));
}
print_r($dates);
Output:
Array(
[0] => Array
(
[start] => 2012-07-07
[end] => 2012-07-09
)
[1] => Array
(
[start] => 2012-07-08
[end] => 2012-07-10
)
[2] => Array
(
[start] => 2012-07-09
[end] => 2012-07-11
)
[3] => Array
(
[start] => 2012-07-10
[end] => 2012-07-12
)
[4] => Array
(
[start] => 2012-07-11
[end] => 2012-07-13
)
[5] => Array
(
[start] => 2012-07-12
[end] => 2012-07-14
)
[6] => Array
(
[start] => 2012-07-13
[end] => 2012-07-15
)
[7] => Array
(
[start] => 2012-07-14
[end] => 2012-07-16
)
[8] => Array
(
[start] => 2012-07-15
[end] => 2012-07-17
)
)
range(date('Y-m-d', strtotime('-4 days'), date('Y-m-d', strtotime('+4 days'))),
You want 9 pairs of dates starting from -4 days of the supplied range, upto +4 days?
Assuming that your dates will be after 1970:
<?php
$start=strtotime($date['start']);
$end=strtotime($date['end']);
for($loop=-4;$loop<=4;$loop++)
{
$loop_str='';
if($loop>=0) $loop_str.='+';
$loop_str.=$loop.' days';
$date['start']=strtotime($loop_str, $start);
$date['end']=strtotime($loop_str, $end);
print_r($date);
}
?>

Categories