First we need to understand two important concepts. Consider the two sentences below:
- the film will be shown at two o'clock in the morning
- the film is two hours long
In the first case, "two hours" refers to timetable (a specific moment of the day). It’s okay that he needs "morning" not to be ambiguous (it could be 2 in the afternoon), but the fact is that he is referring to a specific moment.
In the second case, "two hours" refers to duration (an amount of time). It is not said what time the movie starts, nor will it pass or already has passed. It’s just the amount of time, unrelated to schedules.
These two concepts are not the same thing. Dates and times refer to points in the timeline: a date (day, month and year) refers to a specific point in a calendar, and a time (time, minute, second, fractions of a second) refers to a specific time of a day. Durations are just amounts of time, which exist by themselves, without being tied to a specific date and time.
What confuses is the fact that both (both times and durations) use exactly the same words (days, hours, minutes, etc.), and are often written in the same way (a clock shows "02:00:00" when it is two in the morning, a stopwatch shows "02:00:00" when the time count reaches two hours).
Another point that can - erroneously - make us think that times and durations are the same thing is that, although they are different concepts, they may be related. If I calculate the difference between two dates, the result is a duration (knowing the date/time that started and ended, I can calculate how long it lasted), and if I add a date/time with a duration, the result is another date/time (knowing the date/time that started and how long it lasted, I can calculate the date/time that ended).
That said, a DateTime
to work with dates and times (points in the timeline), but not with durations.
To work with durations, you can use a DateInterval
. With it you can create an instance that corresponds to a certain amount of time, and format it through the method format
. Ex:
$tempo_1 = new DateInterval('PT10H'); // duração de 10 horas
$tempo_2 = new DateInterval('PT18H'); // duração de 18 horas
$tempo_3 = new DateInterval('PT28H'); // duração de 28 horas
$formato = '%H:%I:%S';
echo $tempo_1->format($formato); // 10:00:00
echo $tempo_2->format($formato); // 18:00:00
echo $tempo_3->format($formato); // 28:00:00
Note that the format used is different from the one used in method format
of a DateTime
. To a DateInterval
, besides the letters need to have the %
before, some are different (for example, to format the DateTime
, use the i
minuscule for the minutes and the s
tiny for seconds, but for a DateInterval
one should use I
and S
uppercase so they have zero left for values less than 10).
Another detail is that the builder of DateInterval
receives a duration in ISO 8601 format. Basically, the P
at the beginning is mandatory (comes from the English "Period", another name for "amount of time"). The T
indicates that the following fields refer to hours, minutes and seconds (as before the T
we can have fields for days, months and years - for example, P2Y3MT10H5M
is a duration of 2 years, 3 months, 10 hours and 5 minutes).
In case you only have the total amount of seconds, it wouldn’t do any good new DateInterval("PT{$segundos}S")
, since this class does not transform the total amount of seconds into hours, minutes and seconds (PT120S
- 120 seconds - is formatted as 00:00:120
, and not as 00:02:00
). In this case, you would have to manually calculate the hours, minutes and seconds (as suggested in reply from Guilherme Nascimento) and then create the DateInterval
. Ex:
$seconds = 100800;
// calcular manualmente as horas, minutos e segundos (versão simplificada da resposta do Guilherme Nascimento)
$hours = floor($seconds / 3600);
$mins = floor(($seconds - ($hours * 3600)) / 60);
$secs = floor($seconds % 60);
$tempo_1 = new DateInterval("PT{$hours}H{$mins}M{$secs}S");
echo $tempo_1->format('%H:%I:%S'); // 28:00:00
Although in this case, it seems an exaggeration to use DateInterval
, because you have already calculated each field separately and just print them.
The documentation also suggests other alternatives to turn 100800 seconds in 28 hours, such as this (which uses a logic similar to maniero’s response, to use a DateTime
to get another DateInterval
), or that one (which makes the calculations similar to reply from Guilherme Nascimento). Unfortunately, DateInterval
does not make this conversion natively.
$tempo_1
is UNIX time?– Guilherme Nascimento
I may not have understood or I may be talking nonsense but what you want doesn’t seem possible. The guy
DateTime
expects a valid time (I don’t know, PHP may have subverted this but in decent languages this is how q works), so 28:00:00 is not a possible time in this type.– Maniero
I agree with you @bigown. Class is made to work with Dates, not with time itself. Is there any way (or a gambiarra) that can be done to solve my problem? I’m using a function with a
sprintf
, but I feel uncomfortable with her (besides, she’s "stealing" 1 second of the audio file)– Wallace Maxters
@Guilhermenascimento, I made a small adjustment in the instance of
DateTime
.$tempo_1
in fact it would be the duration in seconds of the audio. In case, I want that if it has100800
(28 hours), I convert it to the format28:00:00
. However, it displays04:00:00
, for he creates1 dia
instead of24 horas
existing within the28 horas
;– Wallace Maxters
@Guilhermenascimento, my value isn’t exactly in
unix time
. But the class works withunix time
(I hope I didn’t say anything stupid)– Wallace Maxters
because date? if this is only about time wouldn’t it be better to work only with Time? Using only the team you wouldn’t have this problem of dates
– SneepS NinjA