Logical doubt: How to find out if an hour is between the hours interval (independent of the day)

Asked

Viewed 724 times

2

Regardless of the time, I need to find out if a time is between the initial and final hour interval, given the 24-hour format. The logic can be both in PHP and MYSQL, since either way should stop a Stored Procedure.

Ex:

Inicio   - Fim       Busca      Esta no intervalo?
07:00:00 - 09:00:00  08:00:00   Sim
19:00:00 - 22:00:00  23:00:00   Não
18:00:00 - 03:00:00  01:00:00   Sim

This does not depend on any date. Only interval of hours even.

This topic almost solve, but did not understand that 01:00:00 is in the interval from 18h to 03h, for example.

  • 2

    01:00:00 is at the interval informed, yes, now. From 18h in the afternoon to 03h in the morning, and the 01:00:00 means that it is 1 am/dawn. If you want to check 1 pm then you should inform 13:00:00

  • Doesn’t that solve? http://stackoverflow.com/questions/19070116/php-check-if-date-between-two-dates

4 answers

3

Solution in PHP

In my view, since we are working with schedules, the easiest is to use the class Datetime PHP. First, let’s define the tests shown in the statement:

$tests = [
  [
    "inicio" => "07:00:00", 
    "final"  => "09:00:00",
    "busca"  => "08:00:00",
    "saida"  => true
  ],[
    "inicio" => "19:00:00", 
    "final"  => "22:00:00",
    "busca"  => "23:00:00",
    "saida"  => false
  ],[
    "inicio" => "18:00:00", 
    "final"  => "03:00:00",
    "busca"  => "01:00:00",
    "saida"  => true
  ],
];

The three proposed tests, composed of the initial, final, the search and the expected output. To run the tests, we used a loop basic:

foreach($tests as $test)
{
    // ...
}

First step is to define the objects relating to the times:

foreach($tests as $test)
{
  $ininio = new DateTime($test["inicio"]);
  $final  = new DateTime($test["final"]);
  $busca  = new DateTime($test["busca"]);
}

As it is clear that it should be independent of the day and that even the interval can start in one day and end in another, as is the case with the third test, we need to make a simple check: if the final time is less than the initial, add at the end an interval of one day.

foreach($tests as $test)
{
  $ininio = new DateTime($test["inicio"]);
  $final  = new DateTime($test["final"]);
  $busca  = new DateTime($test["busca"]);

  if ($final <= $inicio) {
    $final->add(new DateInterval("P1D"));
  }
}

Read more about the class Dateinterval in the documentation. Thus, if the final time is less than the initial one, it is added 24h in it, becoming the same time of the next day.

The same logic applies to the time sought: if it is lower than the initial time, it should be considered as the next day and therefore be added 24h also.

foreach($tests as $test)
{
  $ininio = new DateTime($test["inicio"]);
  $final  = new DateTime($test["final"]);
  $busca  = new DateTime($test["busca"]);

  if ($final <= $inicio) {
    $final->add(new DateInterval("P1D"));
  }

  if ($busca <= $inicio) {
    $busca->add(new DateInterval("P1D"));
  }
}

With this, just check the interval:

foreach($tests as $test)
{
  $ininio = new DateTime($test["inicio"]);
  $final  = new DateTime($test["final"]);
  $busca  = new DateTime($test["busca"]);

  if ($final <= $ininio) {
    $final->add(new DateInterval("P1D"));
  }

  if ($busca <= $ininio) {
    $busca->add(new DateInterval("P1D"));
  }

  if ($busca >= $ininio && $busca <= $final) {
    echo "Sim";
  } else {
    echo "Não";
  }

  echo ", esperado " . ($test["saida"] ? "sim" : "não") . PHP_EOL;
}

I added to the output message the expected value for each test, to serve as a comparison. When executing the code, we will have the output:

Sim, esperado sim
Não, esperado não
Sim, esperado sim

See the code working on Repl.it or in the Ideone.

  • Incredible the power of Datetime(). Thank you very much Anderson and the others.

0

Well, this case is a little simpler if you fix a model of hours, if you are using the model of 24hrs (that the clock starts at 00h and goes until 23h) there just you just count the hours, let’s imagine the following:

  1. You have two strings, the initial interval and the final interval, say 07:00 and 09:00.
  2. Break by ":" you will get two arrays, the first will be Array([0] => '07', [1] => '00') and the second will be Array([0] => '09', [1] => '00').
  3. You will have a third array that will be the time the user is looking for. Do the same with it
  4. First check the time. Se horaUsuario >= horaInicio E horaUsuario <= horaFim then the time is in the interval, the same goes for the minutes. Chain 2 if to make the first case and the second independently, this way if the user no longer has the hours he nor will make the second condition.

There is also the possibility to use the PHP date object itself, as in this topic: https://stackoverflow.com/questions/10351981/php-hours-difference-hhmm-format

0

When I wrote the question, I believed that only with logic would it be possible to solve this pineapple, but I could not. Through Anderson’s code I almost solved, but there are some details. The real case is this: there cannot exist in the bank a record with period overlapping another, ie, if it has '07:00:00' as initial time and '09:00:00' end, could not be added any other period coinciding with this period. Therefore '06:00:00' as '10:00:00' could not be inserted during the 24 hours of the day, this regardless of the day.

Thanks in advance for the personal support.

  • 1

    This completely changes the problem. I suggest you ask another question and make it clear what your need is. Changing the question here will invalidate all answers already given.

0

Yes, in this case, 07:00 to 09:00,

Se horaUsuario >= horaInicio E horaUsuario <= horaFim
would meet the need. However, the problem is when it passes the 0h... imagine the period be
22:00 - 02:00
the search for '01:00' would not work, per hour (searching by number) would be less than 22h.

  • 2

    This is a solution to the question?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.