I have a loop which gives an outcome of number of half hours between given start time and end time
$start = new DateTime('09:00:00');
// add 1 second because last one is not included in the loop
$end = new DateTime('16:00:01');
$interval = new DateInterval('PT30M');
$period = new DatePeriod($start, $interval, $end);
$previous = '';
foreach ($period as $dt) {
$current = $dt->format("h:ia");
if (!empty($previous)) {
echo "<input name='time' type='radio' value='{$previous}|{$current}'>
{$previous}-{$current}<br/>";
}
$previous = $current;
}
the outcome of above loop is as following
09:00am-09:30am
09:30am-10:00am
10:00am-10:30am
10:30am-11:00am
11:00am-11:30am
11:30am-12:00pm
12:00pm-12:30pm
12:30pm-01:00pm
01:00pm-01:30pm
01:30pm-02:00pm
02:00pm-02:30pm
02:30pm-03:00pm
03:00pm-03:30pm
03:30pm-04:00pm
What i am trying to achieve is exclude some of the time mentioned below if it exist in another array $existing_time which looks like this
[0] => Array
(
[start_time] => 2014-03-28T14:00:00+1100
[end_time] => 2014-03-28T14:30:00+1100
)
[1] => Array
(
[start_time] => 2014-03-28T15:00:00+1100
[end_time] => 2014-03-28T15:30:00+1100
)
)
I need help in how to go about doing this, any help will be appreciated
I just added the start times to an array and then check to see if the current start time is in that array. If so, we skip it.
<?php
$start = new DateTime('09:00:00');
$end = new DateTime('16:00:01'); // add 1 second because last one is not included in the loop
$interval = new DateInterval('PT30M');
$period = new DatePeriod($start, $interval, $end);
$existing_time = array(
array(
'start_time' => '2014-03-28T14:00:00+1100',
'end_time' => '2014-03-28T14:30:00+1100'
),
array(
'start_time' => '2014-03-28T15:00:00+1100',
'end_time' => '2014-03-28T15:30:00+1100'
)
);
$booked = array();
foreach ($existing_time as $ex) {
$dt = new DateTime($ex['start_time']);
$booked[] = $dt->format('h:ia');
}
$previous = '';
foreach ($period as $dt) {
$current = $dt->format("h:ia");
if (!empty($previous) && !in_array($previous, $booked)) {
echo "<input name='time' type='radio' value='{$previous}|{$current}'> {$previous}-{$current}<br/>";
}
$previous = $current;
}
See it in action
Related
Situation:
I have arrays with information of the used appointments and the calculated days for the new appointment series based on PHP.
For example, the exist appointment array:
Array
(
[0] => Array
(
[date] => 2019-05-02
[time_start] => 14:00:00
[time_end] => 15:30:00
)
[1] => Array
(
[date] => 2019-05-06
[time_start] => 14:00:00
[time_end] => 15:30:00
)
)
Now, i will check have the calculated series (same array format) collisions with the exist appointments.
My Question:
How can i check if a collision exist beetween the start and end time and if yes how i can give the array a new value with a time windows after or before the exist appointment. This within a time windows from 08:00 am to 4:00 pm.
What i have is the calculation of the appointment days.
private function calculate_dates($data, $measure)
{
$this->load->model('calendar/calendar_model');
$holiday_dates = $this->calendar_model->get_holidays();
foreach ($holiday_dates as $key => $value) {
$holidays[] = $value['holiday_date'];
}
$begin = new DateTime($data->measure_begin);
$end = new DateTime($data->measure_end);
$oneday = new DateInterval("P1D");
$days = json_decode($data->measure_dates);
$wdays = array();
$ue_minutes = 0;
$minutes = ($data->measure_ue * $measure->ue_minutes/2);
$daterange = new DatePeriod( $begin, DateInterval::createFromDateString('+1 weekdays') ,$end );
foreach(new DatePeriod($begin, $oneday, $end->add($oneday)) as $day) {
$day_num = $day->format("N"); /* 'N' number days 1 (mon) to 7 (sun) */
if($day_num < 6 ) { /* weekday */
$wdays[] = $day;
}
}
$count = 1;
foreach($wdays as $date){
foreach ($days as $key => $value) {
if(mb_strtolower($date->format('l')) == $value){
if(($data->measure_ue/2)+1 != $count){
if(in_array($date->format('Y-m-d'), $holidays)) {
$dates[] = $this->close_days($date, $days, true)->format('l, d.m.Y');
} else {
$dates[] = $date->format('l, d.m.Y');
}
$count++;
}
}
}
}
return array(
'dates' => $dates,
'minutes' => round($minutes/count($dates))
);
}
private function close_days($date, $days, $init = false)
{
if($init){
$days[] = 'saturday';
$days[] = 'sunday';
}
if( in_array(mb_strtolower($date->format('l')), $days) ) {
$this->close_days($date->modify('next day'), $days);
}
return $date;
}
Any Ideas for a solution or maybe a code for a better way?
I am trying to Write Program for Calculating Next 20 dates After Specifying Start date, then from 20 dates i have Exclude Weekends & Holidays(Array holidays('2016-12-13',2016-12-24)) And Result Array which includes only Working Days Excluding Saturday & Sunday, from this Result Array after Passing Holiday array(Eg:- holidays('2016-12-13',2016-12-24))), it must be Excluded from result array. i:e;
I want Expected Output Below mentioned
.
<?php
$Date=array('2016-12-01');
echo "\n <br />Start Date:-" . $Date[0] . "";
/*Code For Generating Next 20 Dates Starts*/
//$start = strtotime($s_row['schedule_start_date']);
$start = strtotime('2016-12-01');
$dates=array();
for($i = 0; $i<20; $i++)
{
array_push($dates,date('Y-m-d', strtotime("+$i day", $start)));
}
echo "\n <br /> Array Of next 20 Days/dates of Given:-";
print_r($dates);
$start=array();
$start=$dates; /*Code For Generating Next 20 Dates Ends*/
$result=array();
$start = strtotime(array_values($Date)[0]);
//$end = strtotime(array_values($Date)[30]);
$result = array();
$begin = new DateTime( '2016-12-01' );
$end = new DateTime( '' );
//$end = $end->modify( '+1 day' );
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);
foreach($daterange as $date)
{
//echo $date->format("Y-m-d") . "<br>";
if (date('N', $start) <= 5) /* 'N' number days 1 (mon) to 7 (sun) */
/*5 weekday */
{
$current = date('Y-m-d', $start); //m/d/Y
$result[$current] = '';
}
$start += 86400;
//echo "Days Without Sat Sun".$result[date($date->format("Y-m-d"))];
//echo "Days Without Sat Sun".$result2[date($current->format("Y-m-d"))];
}
echo " \n <br /> Dates Without Weekends LIKE (Excluding Saturday & Sunday):-";
print_r($result);
/*For Holiday*/
$FinalArray = array();
$holidays = array(
'2016-12-13',
'2016-12-24',
);
echo " \n <br /> Given Holiday Dates Are:-";
print_r($holidays);
$a1 = $result;
$a2 = $holidays;
$array = array_diff(array_merge($a1,$a2),array_intersect($a1,$a2));
echo "\n <br /> Output:-";
print_r($array);
?>
it Gives Output as :- Array ( [2016-12-01] => [2016-12-02] => [2016-12-05] => [2016-12-06] => [2016-12-07] => [2016-12-08] => [2016-12-09] => [2016-12-12] => [2016-12-13] => [2016-12-14] => [2016-12-15] => [2016-12-16] => [2016-12-19] => [2016-12-20] => [2016-12-21] => [2016-12-22] => [2016-12-23] => [0] => 2016-12-13 [1] => 2016-12-24 )
> But I Want Expected Output:-
Array ( [2016-12-01] => [2016-12-02] => [2016-12-05] => [2016-12-06] => [2016-12-07] => [2016-12-08] => [2016-12-09] => [2016-12-12] => [2016-12-14] => [2016-12-15] => [2016-12-16] => [2016-12-19] => [2016-12-20] => [2016-12-21] => [2016-12-22] => [2016-12-23]
You Can Notice That 2016-12-13 is Not There in Above Expected Output as in '2016-12-13', 2016-12-24 is passed as Holiday via holiday array ($holidays = array( '2016-12-13', '2016-12-24', );) i:e; if i pass any date through holidays array it should not be included in result Array(). i:e 2016-12-13 is Available in Result array as well as holiday array So While while printing Final OUTPUT:- 13th date(2016-12-13) Should not be Included in final Output. Anybody Solve this will be Appreciated Thanks in Advance.
When I have to remove duplicates from a array the function that I keep going back to is
array array_unique ( array $array [, int $sort_flags = SORT_STRING ] )
you can find the documentation Here
<?php
$input = array("a" => "green", "red", "b" => "green", "blue", "red");
$result = array_unique($input);
print_r($result);
?>
the output
Array
(
[a] => green
[0] => red
[1] => blue
)
I hope that this was able to help
I prefer to calculate all dates just in one pass. (You may skip filling $dates and $dates_mon_fri arrays if they doesn't used in output also.) There is yet another approach to avoid array_diff() and array_unique() functions. I've used an array_flip() to exchange keys with values in $holdidays array to use fast array_key_exists() function.
<?php
$start = strtotime('2016-12-01');
$holidays = [
'2016-12-13',
'2016-12-24',
];
$dates = [];
$dates_mon_fri = [];
$dates_working = [];
$flip_holidays = array_flip($holidays);
for ($i = 0; $i < 20; $i++) {
$timestamp = strtotime("+$i day", $start);
$date = date('Y-m-d', $timestamp);
$dates[] = $date;
$mon_fri = false;
if (date('N', $timestamp) <= 5) {
$dates_mon_fri[] = $date;
$mon_fri = true;
}
if ($mon_fri && !array_key_exists($date, $flip_holidays)) {
$dates_working[] = $date;
}
}
var_dump($dates);
var_dump($dates_mon_fri);
var_dump($dates_working);
You can avoid using explicit looping:
$begin = new DateTimeImmutable('2016-12-01');
$end = $begin->modify('+20 days');
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval, $end);
$allDates = iterator_to_array($daterange);
$datesExcludingWeekends = array_filter($allDates, function ($date) {
return (int) $date->format("N") < 6;
});
$datesExcludingWeekends = array_map(
'date_format',
$datesExcludingWeekends,
array_fill(1, count($datesExcludingWeekends), 'Y-m-d')
);
$holidays = [
'2016-12-13',
'2016-12-24',
];
$datesExcludingWeekendsIncludingHolidays = array_flip(array_merge(
$datesExcludingWeekends,
array_diff($holidays, $datesExcludingWeekends)
));
Here is working demo.
Also, take a look at the Carbon library. If you need some exhaustive working with dates this library can really ease your life.
I am trying to create a schedule of who uses a specific item on which day.
I have 2 arrays.
one with dates &
another with names and how many days they can use the item.
i have managed to create dates array using this.
function dateArray($from, $to, $value = NULL) {
$begin = new DateTime($from);
$end = new DateTime($to);
$interval = DateInterval::createFromDateString('1 day');
$days = new DatePeriod($begin, $interval, $end);
$baseArray = array();
foreach ($days as $day) {
$dateKey = $day->format("d-m-Y");
$baseArray[$dateKey] = $value;
}
return $baseArray;
}
$dates_array = dateArray('01-01-2014', '30-09-2014',true);
print_r($dates_array );
which gives me dates as
Array
(
[01-01-2014] => 1
[02-01-2014] => 1
[03-01-2014] => 1
[04-01-2014] => 1
[05-01-2014] => 1
[06-01-2014] => 1
[07-01-2014] => 1
[08-01-2014] => 1
[09-01-2014] => 1
and so on.
)
i have another array of names having name as key and days as value , they can use the item like this.
$names_array = array("name1" => "4", "name2" => "3", "name3" => "1");
Now i would like to assign names to dates depending on how many days the person can use the item.
like this.
I need my final output array to be like this
Array
(
[01-01-2014] => name1
[02-01-2014] => name1
[03-01-2014] => name1
[04-01-2014] => name1
[05-01-2014] => name2
[06-01-2014] => name2
[07-01-2014] => name2
[08-01-2014] => name3
[09-01-2014] => name1
and so on. notice name1 comes again
)
so i am trying to get output like above but i am failing at the while loop inside the foreach.
so far i have tried this.
function dateArray($from, $to, $value = NULL) {
$begin = new DateTime($from);
$end = new DateTime($to);
$interval = DateInterval::createFromDateString('1 day');
$days = new DatePeriod($begin, $interval, $end);
$baseArray = array();
foreach ($days as $day) {
$dateKey = $day->format("d-m-Y");
$baseArray[$dateKey] = $value;
}
return $baseArray;
}
$dates_array = dateArray('01-01-2014', '30-09-2014',true);
$names_array = array("name1" => "4", "name2" => "3", "name3" => "1");
print_r($dates_array );
$new_dates = array();
foreach($dates_array as $dates => $key){
//echo $dates;
foreach ($names_array as $name => $days){
while($days <= 1){
$new_dates[$dates] = $name ;
$days = $days - 1;
}
}
}
print_r($new_dates);
But my final array is empty.
so how can i solve this ?
You can use a MultipleIterator whereby the second array (names) loops around when needed:
$names_array = array();
// unwind the array values
foreach (array("name1" => "4", "name2" => "3", "name3" => "1") as $value => $freq) {
for ($i = 0; $i < $freq; ++$i) {
$names_array[] = $value;
}
}
// attach both arrays
$m = new MultipleIterator;
$m->attachIterator(new ArrayIterator(array_keys($dates_array)));
$m->attachIterator(new InfiniteIterator(new ArrayIterator($names_array)));
// build final array
$result = array();
foreach ($m as $value) {
$result[$value[0]] = $value[1];
}
It should probably go like this...
while($days <= 1){
$new_dates[$dates] = $name ;
$names_array[$name] = $days - 1;
}
Hi You can try this one
$dates_array = array_keys(dateArray('01-01-2014', '30-09-2014',true));
$names_array = array("name1" => "4", "name2" => "3", "name3" => "1");
$new_dates = array();
$daysindex = 0;
while($daysindex < count($dates_array)){
foreach ($names_array as $name => $day){
for($x = 0; $x<$day; $x++){
if(isset($dates_array[$daysindex])){
$new_dates[$dates_array[$daysindex]] = $name ;
$daysindex++;
}
}
}
}
print_r($new_dates);
$dates = dateArray('01-01-2014', '30-09-2014',true);
$names = array('name1' => 4,'name2' => 3,'name3' => 1);
$count = current($names);
$name = key($names);
foreach($dates as &$value) {
$value = $name;
//if we've displayed a name $count times, move to the next name
if(--$count == 0) {
//if we're at the end of $names, wrap around
if(false === next($names)) {
reset($names);
}
$count = current($names);
$name = key($names);
}
}
print_r($dates);
I have 2 dates. I want to get all months with total days in each.
How can I do this in PHP?
For example
$date1 = '2013-11-13'; // yy-mm-dd format
$date2 = '2014-02-14';
Output
Months Total Days
-----------------------
11-2013 30
12-2013 31
01-2014 31
02-2014 28
Just try with:
$date1 = '2013-11-15';
$date2 = '2014-02-15';
$output = [];
$time = strtotime($date1);
$last = date('m-Y', strtotime($date2));
do {
$month = date('m-Y', $time);
$total = date('t', $time);
$output[] = [
'month' => $month,
'total' => $total,
];
$time = strtotime('+1 month', $time);
} while ($month != $last);
var_dump($output);
Output:
array (size=4)
0 =>
array (size=2)
'month' => string '11-2013' (length=7)
'total' => string '30' (length=2)
1 =>
array (size=2)
'month' => string '12-2013' (length=7)
'total' => string '31' (length=2)
2 =>
array (size=2)
'month' => string '01-2014' (length=7)
'total' => string '31' (length=2)
3 =>
array (size=2)
'month' => string '02-2014' (length=7)
'total' => string '28' (length=2)
Try the below given code :
$date1 = '2013-11-15'; // yy-mm-dd format
$date2 = '2014-02-15';
$start = new DateTime($date1);
$start->modify('first day of this month');
$end = new DateTime($date2);
$end->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("Y-m") ." " ;
echo cal_days_in_month(CAL_GREGORIAN,$dt->format("m"),$dt->format("Y")) . "<br/>";
}
Also, checkout this link for more
i used timestamp and date:
$date1 = '2013-11-15'; // yy-mm-dd format
$date2 = '2014-02-15';
$d1 = strtotime('2013-11-15');
$d2 = strtotime('2014-02-15');
while ($d1 <= $d2) {
echo date('m-d-Y', $d1)." | ";
echo cal_days_in_month(CAL_GREGORIAN, date('m', $d1), date('Y', $d1)) ."<br>";
$d1 = strtotime("+1 month", $d1);
}
This should help you, Check out,
$date1 = new DateTime('2013-11-15');
$date1->modify('first day of this month');
$date2 = new DateTime('2014-02-15');
$date2->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$value = new DatePeriod($date1, $interval, $date2);
foreach ($value as $dates) {
echo $dates->format("m- Y")."-->".cal_days_in_month(0,$dates->format("m"),$dates->format("Y"))."<br>\n";
}
This is what i came up with:
$arr_months = array();
$date1 = new DateTime('2013-11-15');
$date2 = new DateTime('2014-02-15');
$month1 = new DateTime($date1->format('Y-m')); //The first day of the month of date 1
while ($month1 < $date2) { //Check if the first day of the next month is still before date 2
$arr_months[$month1->format('Y-m')] = cal_days_in_month(CAL_GREGORIAN, $month1->format('m'), $month1->format('Y')); //Add it to the array
$month1->modify('+1 month'); //Add one month and repeat
}
print_r($arr_months);
It creates an associative array with the month as key and the number of days as value.
The array created from the example would be:
Array
(
[2013-11] => 30
[2013-12] => 31
[2014-01] => 31
[2014-02] => 28
)
With a foreach loop you will be able to scroll trough the array easily.
You can use the DateTime class along with cal_day_in_month() like this
$datetime1 = "2014-02-15";
$datetime2= "2013-03-15";
$date1 = new DateTime($datetime1);
$date2 = new DateTime($datetime2);
while (date_format($date2, 'Y-m') <= date_format($date1, 'Y-m'))
{
$date2 = $date2->add(new DateInterval('P1M'));
echo $date2->format('Y-m')." | ".cal_days_in_month(CAL_GREGORIAN, $date2->format('m'), $date2->format('Y'))."<br>";
}
What is the most efficient way to get an array of months, from a specified date, up until the present day, grouped by year.
Eg getMonths("August 2012") would output
array(
array("Year"=>"2013", "months" = array(
"February", "January")
),
array("Year"=>"2012", "months" = array(
"December", "November","October", "September", "August")
)
)
So far I've got:
$start = strtotime('2012-08-01');
$end = time();
$month = $start;
$months[] = date('F', $start);
while($month <= $end) {
$month = strtotime("+1 month", $month);
$months[] = date('F', $month);
}
This is outputting the correct months, but not grouping them into years.
Thanks
You can try
function getMonths($month,$count = 1) {
$now = new DateTime();
$start = DateTime::createFromFormat("F Y", $month);
$list = array();
$interval = new DateInterval(sprintf("P%dM",$count));
while ( $start <= $now ) {
$list[$start->format("Y")][] = $start->format("F");
$start->add($interval);
}
return $list;
}
print_r(getMonths("August 2012"));
Output
Array
(
[2012] => Array
(
[0] => August
[1] => September
[2] => October
[3] => November
[4] => December
)
[2013] => Array
(
[0] => January
[1] => February
)
)
Since the answer posted here did not work for me (also tried online sandbox to be sure) i wrote a method that works with the very most versions of PHP:
function getMonths($monat, $year) {
$list = array();
for(;$monat <= 12;$monat++) {
if($year == date("Y") && $monat == date("m")) { // exit on current month+year
break;
}
if(!isset($list[ $year ])) {
$list[ $year ] = array();
}
$list[ $year ][ str_pad($monat, 2, '0', STR_PAD_LEFT) ] = date("F", strtotime('01.' . $monat . '.' . $year));
if($monat == 12) {
$monat = 0;
$year++;
}
}
return $list;
}