问题
I have a system that accepts user submissions, and upon receiving a submission the system will go through all timeslots to find the appropriate timeslot. The problem is that it needs to be able to check against the start & end times if the end time laps to the next day.
Take the following example: A timeslot begins at 10:30 PM on the current day and ends at 4:00 PM the next day. If the current time is between 10:30 PM and 11:59:59 PM, the submission will be assigned to that timeslot. However, if the current time is between 12:00 AM and 4:00 PM then it will skip the timeslot.
This is what I have so far:
function check_time($from, $to, $time) {
$time = strtotime($time);
$from = strtotime($from);
$to_ = strtotime($to);
$to = $to_ <= $from ? strtotime($to . " tomorrow") : $to_;
return ($time >= $from && $time <= $to);
}
$timeslots = array(
array("16:00:00", "22:30:00"),
array("22:30:00", "16:00:00")
);
foreach ($timeslots as $slot) {
if (check_time($slot[0], $slot[1], date("H:i:s")))
{
echo "true\n";
}
else
{
echo "false\n";
}
}
If the current time is 23:00:00, then the result would be
false
true
But if the current time is 12:00:00 then the result would be
false
false
even though it's technically between the two times.
I know it has to do with the fact that if it's a new day, then the strtotime
result for $from
will be later in the day. So instead of checking for 10:30 PM yesterday, it checks for 10:30 PM tonight.
My problem is that I cannot seem to come up with a way to make the $from
time switch to the previous day if it needs to, similar to how I force the $to
time into the next day.
回答1:
This is much easier than you expect. Assume that you have three times, t1
, t2
and tn
which represent from, to and user time respectively. Treat these times as six digit numbers (from 000000 to 235959) and check:
- If
t1
andt2
are present on the same side of midnight boundary- Check if
tn
lies betweent1
andt2
- Check if
- Else
- Check if
tn
does not lie betweent2
andt1
- Check if
Code and tests:
function check_time($t1, $t2, $tn) {
$t1 = +str_replace(":", "", $t1);
$t2 = +str_replace(":", "", $t2);
$tn = +str_replace(":", "", $tn);
if ($t2 >= $t1) {
return $t1 <= $tn && $tn < $t2;
} else {
return ! ($t2 <= $tn && $tn < $t1);
}
}
$tests = array(
array("16:00:00", "22:30:00", "15:00:00"),
array("16:00:00", "22:30:00", "16:00:00"),
array("16:00:00", "22:30:00", "22:29:59"),
array("16:00:00", "22:30:00", "22:30:00"),
array("16:00:00", "22:30:00", "23:59:59"),
array("22:30:00", "16:00:00", "22:29:59"),
array("22:30:00", "16:00:00", "22:30:00"),
array("22:30:00", "16:00:00", "15:59:59"),
array("22:30:00", "16:00:00", "16:00:00"),
array("22:30:00", "16:00:00", "17:00:00")
);
foreach($tests as $test) {
list($t1, $t2, $t0) = $test;
echo "$t1 - $t2 contains $t0: " . (check_time($t1, $t2, $t0) ? "yes" : "no") . "\n";
}
// OUTPUT
//
// 16:00:00 - 22:30:00 contains 15:00:00: no
// 16:00:00 - 22:30:00 contains 16:00:00: yes
// 16:00:00 - 22:30:00 contains 22:29:59: yes
// 16:00:00 - 22:30:00 contains 22:30:00: no
// 16:00:00 - 22:30:00 contains 23:59:59: no
// 22:30:00 - 16:00:00 contains 22:29:59: no
// 22:30:00 - 16:00:00 contains 22:30:00: yes
// 22:30:00 - 16:00:00 contains 15:59:59: yes
// 22:30:00 - 16:00:00 contains 16:00:00: no
// 22:30:00 - 16:00:00 contains 17:00:00: no
回答2:
function check_time($time, $threshold){
$times = array(&$time, &$threshold);
foreach($times as &$ts){
if(!preg_match('~^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$~', $ts)){
return false;
}
$ts = intval(preg_replace('~[^0-9]+~', null, $ts));
}
return ($time >= $threshold) ? 2 : 1;
}
var_dump(check_time(date("H:i:s"), '12:00:00'));
I cheated! Let's follow the logic:
- Any time can be converted to an integer if we remove the punctuation.
- I removed the punctuation from the
$time
you want to test and made it an integer. - I've done the same thing to the
$threshold
which is the date that breaks spaces the slots. - This function just checks if the
$time
integer is before or after the$threshold
. - It cares nothing about dates, tomorrow, time relativity and such.
If it fails (bad input) it returns false
. If it succeeds it returns an integer:
- 1 if before the threshold
- 2 if after the threshold
Hope it fits your needs.
来源:https://stackoverflow.com/questions/17143585/check-if-current-time-is-between-two-times-with-the-possibility-of-lapping-days