Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display anything in php in between particular time duration?

Tags:

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:

  1. 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.

  2. 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

  3. If it Sunday 6pm and Monday 6pm then the override will work for 6 hours on Monday and 18 hours on Monday.

  4. If its Tuesday 6pm and Friday 6pm and today is Tuesday 9pm then the override will apply.

  5. 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.

like image 777
flash Avatar asked Sep 29 '19 02:09

flash


2 Answers

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;
like image 101
Arth Avatar answered Sep 24 '22 23:09

Arth


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.

like image 31
Dharman Avatar answered Sep 23 '22 23:09

Dharman