Calculate price per minute

Asked

Viewed 73 times

1

I need to calculate the price from a starting time, for example the first 30 minutes after the entry costs R$30, after this period each minute needs to add R$1.50:

  • 30 minutes = R$30,00
  • Additional minute = R$1.50

Check in: 10:00
Output: 10:45 am

Price to pay: R$52,50

To count the minute from the time of entry, I am using the code:

date_default_timezone_set('America/Sao_Paulo');
$dataLocal = date('Y-m-d H:i:s');                       

$data1 = $play_hentrada;
$data2 = $dataLocal;
                             
$unix_data1 = strtotime($data1);
$unix_data2 = strtotime($data2);
                             
                             
$nHoras   = ($unix_data2 - $unix_data1) / (60 * 60);
$nMinutos = (($unix_data2 - $unix_data1) % (60 * 60)) / 60;
                             
printf('%02d:%02d', $nHoras, $nMinutos);

I tried to do the calculation like this:

//VALOR MINUTO
$valor_minuto = 1.50;

//TOTAL HORA
$nHoras = number_format($nHoras, 0, '.', '');

//TOTAL MINUTO
$nMinutos = number_format($nMinutos, 2, '.', '');

//TOTAL MINUTOS
$total_minutos = ($nHoras * 60) + $nMinutos;

if($total_minutos < 30){
    $total_sem_minimo = 0;
}else{
    $total_sem_minimo = $total_minutos - 30;
}

$total_total = $total_sem_minimo * $valor_minuto;

$total = $total_total + 30;

$total = number_format($total, 2, '.', '');

echo $total;
  • 1

    Simply calculate the difference in minutes between the time of entry and the time of departure. Subtract 30 of this value, to discount the initial 30 minutes, adding R$ to the total; the remaining minutes you multiply by 1.5 and sum the result in the total.

  • I couldn’t do this calculation, I’m still learning the language :/

  • As you tried to do?

  • edited as I tried to realize the code

1 answer

2

First you need to calculate the total duration in minutes. Then, just see if the duration has passed 30 minutes. If you didn’t pass, the total amount is $30, and if you passed, subtract 30 minutes from the total, and what’s left you multiply by 1.5:

function toMins($horario) {
    list($h, $m) = explode(':', $horario);
    return $h * 60 + $m;
}


$entrada = '10:00';
$saida = '10:45';
$minuto_adicional = 1.5;
$total_minutos = toMins($saida) - toMins($entrada);

if ($total_minutos <= 0) {
    // só por "garantia", verificar se o valor não deu zero ou negativo
    // imprime alguma mensagem de erro, ou não faz nada, vc que sabe
    echo "O horário de entrada é maior ou igual ao de saída";
} else {
    // se entrou nesse else, é porque ficou pelo menos 1 minuto
    // então já paga $30, que é o valor pelos primeiros 30 minutos
    $pagar = 30;
    if ($total_minutos > 30) { // se passou de 30 minutos, cobrar os minutos excedentes
        $pagar += ($total_minutos - 30) * $minuto_adicional;
    }

    $h = floor($total_minutos / 60);
    $m = $total_minutos % 60;
    printf("duração: %02d:%02d\nTotal a pagar: R$%s\n", $h, $m, number_format($pagar, 2, ','));
}

I used number_format to format with two decimal places and comma as decimal separator. The output will be:

duração: 00:45
Total a pagar: R$52,50

Of course, I am assuming that the schedule only has hours and minutes, and that always refer to the same day (there will be, for example, entrance at 23:00 and departure at 02:00 the next day).


It is also worth remembering that number_format returns a formatted string. Of course, if the string is in the "correct" format, PHP can automatically coerce types, but in general, if it is going to do calculations, prefer not to turn the number into a string.


Another way to get the total minutes is by using DateTime:

$total_minutos = ((new DateTime($saida))->getTimestamp() - (new DateTime($entrada))->getTimestamp()) / 60;

The rest of the code is equal. But there’s a catch: when the string only has the time, the DateTime uses the current date and Timezone that is configured in PHP (in your case, you are explicitly setting America/Sao_Paulo - which corresponds to the Time of Brasilia).

In most cases it is no problem, but if you run on a date when daylight saving time changes, it may give differences. For example, when daylight saving time is over, at midnight the clock is set to 23:00, that is, every minute between 23:00 and 23:59 occurs twice (one in daylight saving time and the other in regular time). If you have an interval of hours between 23:00 and 23:59, you have to know which one you refer to - and in this case only the hour and minute is not enough to make the correct calculation. But maybe I’m running too far from the scope of the question...

Another difference is that the DateTime error if the time is invalid (for example, if it is 25:00). Already using the first code, the validation would have to be done manually, something like:

function toMins($horario) {
    list($h, $m) = explode(':', $horario);
    if ($h < 0 || $h > 24) {
        // hora inválida (dar erro, mostrar mensagem, etc)
    }
    if ($m < 0 || $m > 60) {
        // minuto inválido (dar erro, mostrar mensagem, etc)
    }
    return $h * 60 + $m;
}

Anyway, date/time arithmetic is more complicated than it seems, full of corner cases which may or may not be relevant depending on the context. If your entries are controlled (for example, the input and output are always "hour:minute" of the same day), a simpler approach brings no problems. But if you can have schedules on different days, time zones, invalid entries, etc, then it gets more complicated, requiring additional controls (as it is not clear whether this is the case, I will stick to just mentioning that this kind of thing can happen, and in such cases should be taken into account).

  • 1

    +1 for the post however for minutes calculation I would recommend the use of the class Datetime + examples of this post https://stackoverflow.com/questions/365191/how-to-get-time-difference-in-minutes-in-php

  • @Marcosxavier I updated the answer

  • Good. It even works in your first example but will for some reason send ex. 24:61 as time. Possibly give some bug or miscalculation in the flow.

  • @Marcosxavier In this case the DateTime gives error, and the manual calculation accepts (although it should not). I updated the answer again with this detail.

Browser other questions tagged

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