Doubt with logic: How to find out if a time is in the range of hours (independent of the day)

2

Regardless of what time it is, I need to find out if a time is in the range of an initial and final time, given the 24-hour format. The logic can be in both PHP and MYSQL, since in any case you 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

That is without depending on any date. Just hours apart.

This topic almost solved, but I did not understand that 01:00:00 is in the range of 18:00 to 03:00, for example.

    
asked by anonymous 19.03.2017 / 14:10

4 answers

3

Solution in PHP

In my view, since we're working with schedules, the easiest is to use the DateTime class. of 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 tests proposed, consisting of the initial, final, search and expected time. To run the tests, we use a basic loop :

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

First step is to define the time-related objects:

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

As stated in the statement 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 in the case of the third test, we need to do a simple check: final 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. This way, if the final time is less than the initial time, it is added 24h in it, and it will be the same time the next day.

The same logic applies to the search time: if it is less than the start time, it should be considered as the next day and therefore added 24 hours as well.

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 range:

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 the expected value for each test to the output message for 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 at Repl.it or Ideone .

    
20.03.2017 / 03:35
0

Well, this case is a bit simpler if you set a time model, if you are using the 24hrs model (the clock starts at 00h and goes until 11h) then you only have to count the hours, let's imagine the following:

  • You have two strings, the start interval and the ending interval, say 7:00 AM and 9:00 AM.
  • Break by ":" you will get two arrays, the first one will be Array([0] => '07', [1] => '00') and the second one will be Array([0] => '09', [1] => '00') .
  • You will have a third array that will be the time the user is looking for. Do the same with it
  • First check the hours. Se horaUsuario >= horaInicio E horaUsuario <= horaFim so the time is in the range, the same is true for the minutes. Chaining 2 if to make the first case and the second independently, this way if the user does not have the hours he will not even make the second condition.
  • There is also the possibility of using the PHP date object itself, as in this topic: link

        
    19.03.2017 / 19:52
    0

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

    Se horaUsuario >= horaInicio E horaUsuario <= horaFim
    would meet the need. However, the problem is when it goes from 0h ... imagine the period being
    22:00 - 02:00
    the search for '01: 00 'would not work, per hour (searching by number) would be less than 22h.     
    20.03.2017 / 02:57
    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 it, but it lacks some details. The real case is this: there can not be a record in the bank with period overlapping another one, that is, if it has '07: 00: 00 'as the start time and' 09: 00: 00 ', no other could be added period coincided with this period. Therefore '06: 00: 00 'at '10: 00: 00' could not be inserted during the 24 hours of the day, this regardless of the day.

    Thanks in advance for your personal support.

        
    20.03.2017 / 23:06