First, you could use the input type="time"
instead of type="text"
. If the browser is compatible and support this type, it already limits the input format to hh:mm
(if the browser does not support, at the end of the answer there is an alternative).
Unfortunately the Javascript does not provide a way to work only timeslot, since the class Date
actually represents a timestamp (a specific time line, and therefore may represent a different date and time in each time zone).
An alternative is to do the Parsing manually, and calculate the difference in minutes between times. The value of a field input type="time"
is the time in the format hh:mm
, where the time field varies between 0 and 23. Thus, a way to separate the time from the minutes is by using split
to break the string into two parts, and parseInt
to convert these strings to numbers. Example:
let [hora, minuto] = '10:00'.split(':').map(v => parseInt(v));
The above line works if the browser already supports Destructuring Assignment and Arrow Functions. If the browser does not support this syntax, you can do:
let partes = '10:00'.split(':');
let hora = parseInt(partes[0]);
let minuto = parseInt(partes[1]);
Then simply calculate the difference in minutes between those times and at the end convert this difference in minutes to the equivalent in hours and minutes. The code follows below (I have "cleaned" your HTML, removing the div
's and CSS classes, just to focus on the mechanism itself):
function ajustaHorario(idCampo) {
let valorCampo = document.getElementById(idCampo).value;
let [hora, minuto] = valorCampo.split(':').map(v => parseInt(v));
return (hora * 60) + minuto;
}
function calculaTotal() {
// diferença entre horário de início e o início do intervalo
let totalAntesIntervalo = ajustaHorario('intervaloInicio') - ajustaHorario('horarioInicio');
// diferença entre fim do intervalo e o horário de término
let totalDepoisIntervalo = ajustaHorario('horarioFim') - ajustaHorario('intervaloFim');
// tempo total (em minutos)
let total = totalAntesIntervalo + totalDepoisIntervalo;
// quebrar o total em horas e minutos
let totalHoras = Math.floor(total / 60);
let totalMinutos = total % 60;
// colocar o valor no campo
document.getElementById('cargaHorariaTotal').value = totalHoras + ' horas e ' + totalMinutos + ' minutos';
}
<label for="horarioInicio"><br>Horário de início:</label>
<input type="time" id="horarioInicio" placeholder="Exemplo: 08:00" />
<label for="intervaloInicio"><br>Início do intervalo:</label>
<input type="time" maxlength="5" id="intervaloInicio" placeholder="Exemplo: 12:00" />
<label for="intervaloFim"><br>Fim do intervalo:</label>
<input type="time" maxlength="5" id="intervaloFim" placeholder="Exemplo: 13:00" />
<label for="horarioFim"><br>Horario de Término:</label>
<input type="time" maxlength="5" id="horarioFim" placeholder="Exemplo: 18:00" />
<br><label for="carga-horaria">Carga Horária Total:</label>
<input type="text" id="cargaHorariaTotal" readonly>
<br><input type="button" value="Calcular Total" onclick="calculaTotal()">
The full time load format is in text ("X hours and Y minutes"), but you can also put in other formats such as hh:mm
. Just remembering that this format is for time of day, but what the total value represents is actually a duration. Those are two things you shouldn’t confuse:
- a time represents a specific point day. Ex: break started at 11:30 (11 hours and 30 minutes, morning)
- a duration represents a quantity of time. Ex: today I worked 8 hours and 20 minutes (I didn’t say what hours I started or finished, if I had break, none of that, it’s just the amount time, not necessarily related to a specific time)
Although they both use the same words (hours, minutes, etc), they are not the same thing. The fields input type="time"
represent times, and the total that has been calculated represents a duration.
You can even write a duration of 8 hours and 20 minutes as "08:20"
, but should not confuse this with the "8 and 20 in the morning" time. I have chosen to write the duration as text, but if you want, you can format it as hh:mm
:
document.getElementById('cargaHorariaTotal').value =
totalHoras.toString().padStart(2, '0')
+ ':' + totalMinutos.toString().padStart(2, '0');
This code is very "naive" because it does not check if the departure time is greater than the input, for example. You can make this check by comparing the values of ajustaHorario(campo)
. In addition, the code only deals with schedules, so it is assumed that all schedules belong to the same day.
If the browser does not support the input type="time"
When the browser does not support the input type="time"
, this behaves like a common text field. But you can limit the values accepted using a pattern
, in accordance with suggested in the documentation.
In the example below I put the field as text
just for you to see how it would work if the field were time
and the browser did not support it. But in your code I would always leave as time
:
<form>
<input type="text" id="horarioInicio" placeholder="Exemplo: 08:00" required
pattern="([01][0-9]|2[0-3]):([0-5][0-9])"/>
<input type="submit" value="submit">
</form>
Thus, the field only accepts values in the format hh:mm
, hours between 00 and 23 and minutes between 00 and 59.
The pattern
contains a regular expression (also called regex), indicating the format accepted in the field.
The brackets form a character class. For example, [01]
means "the digit zero or the digit 1", while [0-9]
is "any digit from 0 to 9".
The |
means alternation, then [01][0-9]|2[0-3]
means:
- digit 0 or 1, followed by a digit from 0 to 9, or
- digit 2, followed by a digit from 0 to 3
With that, I guarantee the hours can be from 00 to 23.
Next we have :
, and finally [0-5][0-9]
(a digit from 0 to 5, followed by a digit from 0 to 9), ensuring that minutes can be from 00 to 59.