I have a php code as shown below in which I want to display anything in between two calendar days of the week.
The values coming inside $data->{"select_start_day"};
$data->{"start_time"};
$data->{"select_end_day"};
and $data->{"end_time"};
is controlled by the user.
PHP Code:
if (file_exists('feeds/ptp-ess_landing.json')) {
$data = json_decode(file_get_contents('feeds/ptp-ess_landing.json'));
}
date_default_timezone_set('America/Toronto');
$arradate = strtolower(date('D'));
$nowtime = (int)date('His');
$start_day=$data->{"select_start_day"};
$start_time=$data->{"start_time"};
$end_day=$data->{"select_end_day"};
$end_time=$data->{"end_time"};
For example, let us suppose the user enter $start_day
as sun
$start_time
as 143400
$end_day
as wed
$end_time
as 140000
The above time duration means we are in range and it should display anything we want to display until tomorrow 2pm as tomorrow is wednesday. I am in EST.
I am using the following code in order to pull the current day of the week and time:
date_default_timezone_set('America/Toronto');
$arradate = strtolower(date('D'));
$nowtime = (int)date('His');
Problem Statement:
I am wondering what if logic I need to use so that its print anything Sunday
143400
and Wednesday
140000
.
if() {
echo "Its in range";
}
Cases:
If the override is supposed to apply from Monday at 8am to Monday at 6pm and today is Wednesday then the override doesn't apply.
If its Monday 6 pm and Friday 6 pm then the override will work for 6 hours on Monday, Tuesday whole day, Wednesday whole day, Thursday whole day, Friday upto 6pm
If it Sunday 6pm and Monday 6pm then the override will work for 6 hours on Monday and 18 hours on Monday.
If its Tuesday 6pm and Friday 6pm and today is Tuesday 9pm then the override will apply.
if its Thursday 6pm and Wednesday 6pm then the override will work for 6 hours on thursday, 24 hours on Friday, 24 hours on Saturday, 24 hours on Sunday, 24 hours on Monday, 24 hours on Tuesday, 24 hours on Wednesday and 18 hours on Thursday.
The difficult part of this question lies in handling ranges that 'wrap' around the end of the week, i.e. your example case 5
I'd suggest setting up a reference array of days that covers two weeks
$days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
$days = array_merge($days, $days);
Slice it so that it starts at the day of the start point (it will be reindexed from 0)
$days = array_slice($days, array_search($startDay, $days));
You can then build a reference integer for both now and the end point
$nowRef = (int) (array_search($nowDay, $days) . $nowTime);
$endRef = (int) (array_search($endDay, $days) . $endTime);
Note that you could do the same for the start point, but as the days array starts with $startDay
(index 0) this is equivalent to $startTime
Your if condition then simply becomes
if ($nowRef >= $startTime && $nowRef <= $endRef) {
// IN RANGE
}
N.B. This assumes that your user inputs have been validated, and that if the start day and end day are the same then the end time is greater than the start time
Your naming convention is a bit inconsistent, so I have renamed some of your variables and switched to camel case for readability
$nowDay = $arradate;
$nowTime = $nowtime;
$startDay = $start_day;
$startTime = $start_time;
$endDay = $end_day;
$endTime = $end_time;
Here is my stab at it, using a mapping table and string concatenation. It doesn't work if the days are in reversed order. e.g. If today is Sunday and the value of select_start_day
is Fri
and the value of select_end_day
is Mon
, then it won't work.
<?php
$arr = (object) [
'select_start_day' => 'wed',
'start_time' => 143400,
'select_end_day' => 'wed',
'end_time' => 220000
];
$map_daysToNumbers = ['sun'=>1, 'mon'=>2, 'tue'=>3, 'wed'=>4, 'thu'=>5, 'fri'=>6, 'sat'=>7];
$startString = $map_daysToNumbers[$arr->select_start_day] . str_pad($arr->start_time, 6, '0', STR_PAD_LEFT);
$endString = $map_daysToNumbers[$arr->select_end_day] . str_pad($arr->end_time, 6, '0', STR_PAD_LEFT);
$tz = new \DateTimeZone('America/Toronto');
$today = new \DateTime('now', $tz);
$todayString = ($today->format('w')+1) . $today->format('His');
if($startString <= $todayString && $todayString <= $endString){
echo 'In range';
}
or date-based solution. Neither of them is guaranteed to fulfil your needs.
$arr = (object) [
'select_start_day' => 'tue',
'start_time' => 143400,
'select_end_day' => 'wed',
'end_time' => 220000
];
$tz = new \DateTimeZone('America/Toronto');
// extrapolate the start date looking 7 days back
$sDate = new \DateTime('tomorrow midnight', $tz);
$sDate->modify('last '.$arr->select_start_day);
$sDate->setTime(...str_split(str_pad($arr->start_time, 6, '0', STR_PAD_LEFT), 2));
// or bound the start date to be between last sunday and next saturday
$sDate = new \DateTime('Saturday last week', $tz);
$sDate->modify('next '.$arr->select_start_day);
$sDate->setTime(...str_split(str_pad($arr->start_time, 6, '0', STR_PAD_LEFT), 2));
// extrapolate the end date
$eDate = clone $sDate;
$eDate->modify('yesterday'); // workaround to consider the same day possibility
$eDate->modify('next '.$arr->select_end_day);
$eDate->setTime(...str_split(str_pad($arr->end_time, 6, '0', STR_PAD_LEFT), 2));
// Test against today
$today = new \DateTime('now', $tz);
var_dump($sDate);
var_dump($eDate);
var_dump($today);
if($sDate <= $today && $today <= $eDate){
echo 'In range';
}
The first way will always start in the past and depending on your range it might include today or not. The second will always be bound to the current week, which I believe is what you wanted.
As @mickmackusa and I said in the comments, the requirements given to you are vague and imprecise. You either need more rigid rules or a date based solution, i.e. you are given two precise dates (timestamps) and then you compare if a date falls between them. This is what I tried to do in my second option, but It is unknown if the date should be in the past or future.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With