Differentiate output message depending on time in array - php

I am trying to write a script which will display either an open or closed message depending on a businesses operating hours. I tried using the solution found here and adding to this by setting the timezone. However when I try to run this the value of $status is always 'closed' even if the time of day falls within the values in the array.
Here is my code, any advice would be appreciated. Thanks
//setting default timezone
date_default_timezone_set('Europe/Dublin');
//creating array of opening hours
$openingHours = [
'Sun' => ['12:00' => '20:30'],
'Wed' => ['16:00' => '21:00'],
'Thu' => ['16:00' => '21:00'],
'Fri' => ['16:00' => '23:00'],
'Sat' => ['16:00' => '21:00']
];
//current timestamp
$timestamp = time();
//default status
$status = 'closed';
//get time object from timestamp
$currentTime = (new DateTime())->setTimestamp($timestamp);
//loop through time range for current day
foreach ($openingHours[date('D', $timestamp)] as $startTime => $endTime) {
//create time objects from start and end times
$startTime = DateTime::createFromFormat('h:i A', $startTime);
$endTime = DateTime::createFromFormat('h:i A', $endTime);
//check if current time is within range
if (($startTime < $currentTime) && ($currentTime < $endTime)) {
$status = 'open';
break;
}//end off if
}//end off foreach
echo "we are currently :$status";

In your code the currentTime variable is an object so when you try comparing it things aren't going to match. Try this instead which simplifies things a little.
date_default_timezone_set('Europe/Dublin');
//creating array of opening hours
$openingHours = [
'Sun' => ['12:00' => '20:30'],
'Wed' => ['16:00' => '21:00'],
'Thu' => ['16:00' => '21:00'],
'Fri' => ['16:00' => '23:00'],
'Sat' => ['16:00' => '21:00']
];
//default status
$status = 'closed';
$timeNow = date('H:m',time());
//loop through time range for current day
foreach ($openingHours[date('D', time())] as $startTime => $endTime) {
//check if current time is within range
if (($startTime < $timeNow) && ($timeNow < $endTime)) {
$status = 'open';
break;
} //end off if
} //end off foreach
echo "we are currently :$status";
Edit on July 7th:
If you can change you the opening hours array slightly you may avoid multiple calls to date and the foreach loop using the code below.
date_default_timezone_set('Europe/Dublin');
//creating array of opening hours
$openingHours = [
'Sun' => ['Open'=>'12:00','Close' => '20:30'],
'Wed' => ['Open'=>'16:00','Close' => '21:00'],
'Thu' => ['Open'=>'16:00','Close' => '21:00'],
'Fri' => ['Open'=>'16:00','Close' => '23:00'],
'Sat' => ['Open'=>'16:00','Close' => '21:00']
];
$timeNow = date('H:m',time());
$dow = date('D',time());
echo 'We are currently :' . ((($openingHours[$dow]['Open'] < $timeNow) AND
($timeNow < $openingHours[$dow]['Close'])) ? 'open' : 'closed');

Related

Seeking logic to scan array for next active time slot

I'm trying to define the logic that would return a value of the next live show time per day for a media station.
The array
$liveshows = [
'mon' => [
['start' => '0600', 'end' => '0900', 'host' => 'Joe'],
['start' => '1300', 'end' => '1500', 'host' => 'Carol'],
['start' => '1500', 'end' => '1600', 'host' => 'Cortez'],
['start' => '1700', 'end' => '2100', 'host' => 'Boy George']
],
];
Process
date_default_timezone_set('America/New_York');
$day = strtolower(date('D'));
$current_time = date('Hi');
$html=''; $start=[];
if( $day == 'mon' && !empty( $liveshows['mon'] ) )
{
foreach( $liveshows['mon'] as $showtime ) {
if( $current_time >= $showtime['start'] && $current_time <= $showtime['end'] )
$html .= '<h3>' . $showtime['host'] . ' <span>is on air</span></h3>';
// create an array of start times to use in below 'no live show' notice.
$start[] = $showtime['start'];
}
}
// print it
echo $html;
All works fine to that point.
Now I want to show a notice when there is no live host on air so I've used current(), next() and end() to cycle the $start array. It works to a point but fails because the array count() is not consistent per day.
if( empty( $html ) )
{
$nextshow='';
if( $current_time < current($start) ) {
$nextshow = current($start);
}
elseif( $current_time < next($start) ) {
$nextshow = next($start);
}
echo '<h3>No live show is on</h3>';
echo '<p>The next live show is at ' . date('g:iA', strtotime( $nextshow )) . '</p>';
}
The output notice when retrieved is:
From midnight
The next live show is at 6:00AM
Between first show and next
The next live show is at 1:00PM
After the 1600 (4PM) show end time, the process fails and the output is without the 5PM value for the next in array and just...
The next live show is
How do I correctly scan the array and compare to current time to check if a show is on, and if not, show the time of the next show in line?
I think it's quite cumbersome to use current/next in your case. You can simplify your code greatly by keeping track on whether any show is on air $isOnAir = true/false (in below code) and if not, simply reiterating the shows array with a different condition.
Example:
<?php
declare(strict_types=1);
date_default_timezone_set('America/New_York');
$day = strtolower(date('D'));
$current_time = date('Hi');
// test
$day = 'mon';
$current_time = '1630';
$liveshows = [
'mon' => [
['start' => '0600', 'end' => '0900', 'host' => 'Joe'],
['start' => '1300', 'end' => '1500', 'host' => 'Carol'],
['start' => '1500', 'end' => '1600', 'host' => 'Cortez'],
['start' => '1700', 'end' => '2100', 'host' => 'Boy George'],
],
];
if ($day === 'mon' && !empty($liveshows['mon'])) {
// assume no show is on air
$isOnAir = false;
foreach ($liveshows['mon'] as $showtime) {
if ($showtime['start'] <= $current_time && $current_time <= $showtime['end']) {
// we have a show on air
$isOnAir = true;
// output
echo '<h3>', $showtime['host'], ' <span>is on air</span></h3>';
// break loop
break;
}
}
// without a show on air (see above)
if (!$isOnAir) {
echo '<h3>No live show is on</h3>';
foreach ($liveshows['mon'] as $showtime) {
// find the first where start > current
if ($current_time < $showtime['start']) {
// output
echo '<p>The next live show is at ', date('g:iA', strtotime($showtime['start'])), '</p>';
// and break loop
break;
}
}
}
}
https://3v4l.org/ZKcjo

Carbon - Laravel - Separate by Days

Look guys , i have two functions.
public function date(){
BusinessTime::enable(Carbon::class);
BusinessTime::enable(Carbon::class, [
'sunday' => ['08:00-22:00'],
'monday' => ['08:00-22:00'],
'tuesday' => ['08:00-22:00'],
'wednesday' => ['08:00-22:00'],
'thursday' => ['08:00-22:00'],
'friday' => ['08:00-23:59'],
'saturday' => ['00:00-23:59'],
'holidaysAreClosed' => true,
]);
$options = 0;
$date1 = Carbon::parse('2020-11-20 20:00')->diffInBusinessHours('2020-11-22 16:00:00', $options);
$date2 = $this->date2();
$date3 = $date2 - $date1;
echo 'Hours In'.round($date1);
echo '<br>';
echo 'Horas Out'.round($date3);
}
that return me all the hours , that are inside my range of bussiness hours .
and i have another function that return me all time between two dates .
public function date2(){
$start = Carbon::create(2020,11,20,20,0,0,'America/Recife');
$end = Carbon::create(2020,11,22,16,0,0,'America/Recife');
$options = 0;
return $start->diffInHours($end);
}
but how could i return on fuction date() , for example returne the diffInBusinessHours separate by day , where could be a array of date and hours . its possible ?
Are you using kylekatarnls/business-time?
If so, have you tried using $carbonDate->getOpeningHours() or Carbon::getOpeningHours()?

PHP - Date range by month

I have a date range and I need it to group by month but I want to keep starting day and ending day. So far I have this:
$interval['from'] = '2017-01-02 00:00:00';
$interval['to'] = '2017-02-06 23:59:59';
$start = Carbon::createFromFormat('Y-m-d H:i:s', $interval['from'])->startOfMonth();
$end = Carbon::createFromFormat('Y-m-d H:i:s', $interval['to'])->startOfMonth()->addMonth();
$separate = CarbonInterval::month();
$period = new \DatePeriod($start, $separate, $end);
foreach ($period as $dt) {
dump($dt);
}
But as result I'm getting:
Carbon\Carbon(3) {
date => "2017-01-01 00:00:00.000000" (26)
timezone_type => 3
timezone => "Europe/Prague" (13)
}
Carbon\Carbon(3) {
date => "2017-02-01 00:00:00.000000" (26)
timezone_type => 3
timezone => "Europe/Prague" (13)
}
It is grouped by month but I need to get whole month period, I mean from
2017-01-02 00:00:00 to 2017-01-31 23:59:59
2017-02-01 00:00:00 to 2017-02-06 23:59:59.
Output:
$array = [
0 => [
'from' => '2017-01-02 00:00:00',
'to' => '2017-01-31 23:59:59'
],
1 => [
'from' => '2017-02-01 00:00:00',
'to' => '2017-02-06 23:59:59'
]
];
What is the easiest way to achive it?
Edit: Here is a little bit modified Carbon version of accepted answer, maybe somebody will need it:
$interval['from'] = '2017-01-02 00:00:00';
$interval['to'] = '2017-04-08 23:59:59';
$interval_from = Carbon::createFromFormat('Y-m-d H:i:s', $interval['from']);
$interval_to = Carbon::createFromFormat('Y-m-d H:i:s', $interval['to']);
$result = [];
foreach (range($interval_from->month, $interval_to->month) as $x) {
$to = $interval_from->copy()->endOfMonth();
if ($x == $interval_to->month) {
$result[] = ["from" => $interval_from, "to" => $interval_to];
} else {
$result[] = ["from" => $interval_from, "to" => $to];
}
$interval_from = $to->copy()->addSecond();
}
PHP code demo
Try this solution you can change from one month to another month(not year) and then check. Lengthy solution but hopefully works correctly, putting explaination.
<?php
ini_set('display_errors', 1);
$from=$interval['from'] = '2017-01-02 00:00:00';
$interval['to'] = '2017-03-07 23:59:59';
$month1=date("m", strtotime($interval['from']));
$month2=date("m", strtotime($interval['to']));
$result=array();
foreach(range($month1, $month2) as $x)
{
$dateTimeObj= new DateTime($from);
$dayDifference=($dateTimeObj->format('d')-1);
$dateTimeObj= new DateTime($from);
$dateTimeObj->add(new DateInterval("P1M"));
$dateTimeObj->sub(new DateInterval("P".$dayDifference."DT1S"));
$to= $dateTimeObj->format("Y-m-d H:i:s");
if($x==$month2)
{
$dateTimeObj= new DateTime($interval['to']);
$noOfDays=$dateTimeObj->format("d");
$dateTimeObj->sub(new DateInterval("P".($noOfDays-1)."D"));
$from=$dateTimeObj->format("Y-m-d H:i:s");
$result[]=array("from"=>$from,"to"=>$interval['to']);
}
else
{
$result[]=array("from"=>$from,"to"=>$to);
}
//adding 1 second to $to for next time to be treated as $from
$dateTimeObj= new DateTime($to);
$dateTimeObj->add(new DateInterval("PT1S"));
$from= $dateTimeObj->format("Y-m-d H:i:s");
}
print_r($result);

PHP Conditionally Combining Arrays

I'm looping through an array of days in the current month to generate another array of days that are on or after the current day. I'm also doing the same for the next month (which will always include all days as they are after the current date).
The complexity is when the next month is in a different year to the current month. The format of the final array is like this:
array("year" => array("month" => array(days)));
When both months are in the same year it might look like this:
$allDays = array("2013" => array( "11" => array(28,29,30), "12" => array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31)));
When the 2 months are in different years (i.e. Dec and Jan) it might look like this:
$allDays = array("2013" => array("12" => array(2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31)), "2014" => array("1" => array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31) )) ;
Here's my code that generates the list of dates for the current month and the next month:
// Set the default timezone
date_default_timezone_set('Australia/Sydney');
// Get days for current month
$day = date("Y-m-d");
$i = strtotime($day);
array("year" => array("month" => array(days)));
$linked_days = array(
date('Y', $i) => array(
date('m') => range(date('d', $i), intval(date('t'))),
),
);
// Get days for next month
$day2 = date("Y-m-d", strtotime('first day of next month')) ;
$i2 = strtotime($day2);
array("year" => array("month" => array(days)));
$linked_days2 = array(
date('Y', $i2) => array(
date('m') => range(date('d', $i2), intval(date('t'))),
),
);
I'm not sure how to go about combining them into the 1 array with a different sytanx if they are in the same year or not?
You can check if there is already an entry for the year in your array with isset function :
Change this
$day2 = date("Y-m-d", strtotime('first day of next month')) ;
$i2 = strtotime($day2);
array("year" => array("month" => array(days)));
$linked_days2 = array(
date('Y', $i2) => array(
date('m') => range(date('d', $i2), intval(date('t'))),
),
);
To
$day2 = date("Y-m-d", strtotime('first day of next month')) ;
$i2 = strtotime($day2);
array("year" => array("month" => array(days))); //useless line ??
if(!isset($linked_days[date('Y', $i2)])){
//if no entry for this year in array, create new entry
$linked_days[date('Y', $i2)] = array(date('m') => range(date('d', $i), intval(date('t'))));
}
else{
//else, just add the month entry
$linked_days[date('Y', $i2)][date('m')] = range(date('d', $i2), intval(date('t'))) ;
}

Logo change with date script

I just wondered if anybody can point me in the right direction: I'm looking to make a script whereby the logo on my site changes depending on the date; so for instance a haloween style one soon.
I started off by having 2 arrays, 1 of start dates and 1 of end dates(not sure even if this is the best way!):
<?php
$start_dates = array('01/01' => 'New Years',
'14/02' => 'Valentine Day',
'16/02/2010' => 'Pancake Day',
'17/03' => 'St Patricks Day',
'01/04' => 'April Fools',
'02/04/2010' => 'Easter',
'23/04' => 'St Georges Day',
'11/06/2010' => 'World Cup',
'31/10' => 'Halloween',
'05/11' => 'Guy Fawkes',
'11/11' => 'Armistice Day',
'16/10' => 'Today',
'15/12' => 'Christmas');
$end_dates = array( '08/01' => 'New Years',
'15/02' => 'Valentine Day',
'17/02/2010' => 'Pancake Day',
'18/03' => 'St Patricks Day',
'02/04' => 'April Fools',
'06/04/2010' => 'Easter',
'24/04' => 'St Georges Day',
'12/07/2010' => 'World Cup',
'01/11' => 'Halloween',
'06/11' => 'Guy Fawkes',
'12/11' => 'Armistice Day',
'17/10' => 'Today',
'01/01' => 'Christmas');
?>
Easy so far...the problemis that I need a way of working out if todays date falls between the start date and end date, then changing the image file name.
Its a long shot but I hope someone would be kind enough to help.
Thanks,
B.
like this
$events = array(
'New Year' => '01/01 01/08',
'Pancake Day' => '16/02/2010 17/02/2010',
//etc
);
echo find_event($events, '16/02');
where find_event() is
function mdy2time($date) {
$e = explode('/', $date);
if(count($e) < 3)
$e[] = '2010';
return strtotime("$e[1]-$e[0]-$e[2]");
}
function find_event($events, $date = null) {
$date = is_null($date) ? time() : mdy2time($date);
foreach($events as $name => $range) {
list($start, $end) = explode(' ', $range);
if($date >= mdy2time($start) && $date <= mdy2time($end))
return $name;
}
return null;
}
you should use an array more like this:
$dates = array();
$dates[] = array(
'name' => 'New Years'
'start' = '01/14',
'end' => '01/20',
'style' => 'haloween',
);
$dates[] = array(
//...
);
then you can get the style as follows:
$style='default';
// date as number e.g. 130 (january 30th)
$currDate = date('md',time()) * 1;
foreach ($dates AS $k => $v) {
$tmp = explode("/",$v['start'];
$start = ($tmp[1].$tmp[0])*1;
$tmp = explode("/",$v['end'];
$stop = ($tmp[1].$tmp[0])*1;
if ($start <= $currDate && $currDate < $stop) {
$style=$v['style'];
break;
}
}
echo 'style: '.$style;
Didn't check the code yet, so feel free to correct me if iam wrong.

Categories