Разница между продолжительностью

Я создаю расписание, в котором отображаются ожидаемые и фактические часы.

Продолжительность сохраняется, как показано ниже.

23:15 - 23 часа 15 минут

25:45 - 25 часов 45 минут

Мне нужно определить разницу в часах и минутах между ними (дополнительные часы работы)

Я пробовал следующее

$acutal=='23:15';
$expected=='25:45';
$start_time = new DateTime("1970-01-01 $acutal:00");
$time = $start_date->diff(new DateTime("1970-01-01 $expected:00"));

Это работает, однако, когда часы превышают 24:00, выдает ошибку (очевидно, потому что он считывает его как время)

Uncaught exception 'Exception' with message 'DateTime::__construct(): Failed to parse time string (1970-01-01 25:45:00)

Есть другой способ сделать это?

Если вас не интересуют часовые пояса и тому подобное, вероятно, проще всего просто преобразовать в минуты, вычесть и преобразовать обратно. Не нужно добавлять сложность создания реальных объектов стиля DateTime.

CollinD 02.05.2018 21:14

@CollinD - не могли бы вы привести пример?

Shane 02.05.2018 21:17
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
2
52
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете проверить, превышает ли количество часов 24, и если да, добавить день и удалить 24 часа.

$actual='23:15';
$expected='25:45';

$day = 1;
list($hrs, $min) = explode(':', $expected);
if ($hrs > 24) { $day += 1; $hrs -= 24; }

$start_time = new DateTime("1970-01-01 $actual:00");
$time = $start_time->diff(new DateTime("1970-01-$day $hrs:$min:00"));

echo $time->format('%hh %Im');

Выход:

2h 30m

Также обратите внимание, что == используется для сравнения, а не для назначения.

Вы также можете заменить if ($hrs > 24) на while(), если осталось 48 часов или больше.


редактировать

Как указывает @CollinD, если время превышает количество дней в месяце, он завершится ошибкой. Вот еще одно решение:

$actual='23:15';
$expected='25:45';

list($hrs, $min) = explode(':', $actual);
$total1 = $min + $hrs * 60;

list($hrs, $min) = explode(':', $expected);
$diff = $min + $hrs * 60 - $total1;

$start_time = new DateTime();
$expected_time = new DateTime();
$expected_time->modify("+ $diff minutes");
$time = $start_time->diff($expected_time);

echo $time->format('%hh %Im');

В качестве предупреждения я подозреваю, что это столкнется с той же проблемой, что и раньше, если ваша продолжительность превысит количество часов в январе 1970 года.

CollinD 02.05.2018 21:45

Вы правы, @CollinD, спасибо. Я обновил ответ на новый способ сделать это.

Syscall 02.05.2018 21:56

Если вы уже конвертируете все в минуты, кажется, что лучше всего просто устранить сложность, добавленную с помощью DateTime все вместе. Длительности на самом деле являются просто скалярами с размерным временем, поэтому добавление временного контекста вызывает только странные проблемы с крайним случаем, imo.

CollinD 02.05.2018 22:12

Спасибо за интересный комментарий @CollinD. (Я немного изменил код). Объект DateInterval позволяет форматировать, и я использовал это для сопоставления с исходным кодом OP.

Syscall 02.05.2018 22:40

@Syscall - ваше обновление возвращает 0h 00m при использовании этих переменных $actual='34:50'; $expected='22:00';

Shane 04.05.2018 14:45

@Shane: См. 3v4l.org/Qev4c: $expected_time->modify(($diff < 0 ? '' : '+') . "$diff minutes"); или используйте abs($diff), или проверьте, не превышает ли значение $ actual, чем ожидалось, и инвертируйте их. Это произошло потому, что строка в modify() была "+ -770 minutes".

Syscall 04.05.2018 14:50

Вы можете попробовать использовать функции datetime, но мне кажется более простым рассматривать время как строку, использовать split или explode, чтобы получить часы и минуты, преобразовать в целые числа, получить разницу в минутах и ​​преобразовать обратно в часы и минуты ( целое деление на 60 и остаток).

$t1=explode(':',$expected);
$t2=explode(':',$actual);
$d=60*($t1[0]-$t2[0])+t1[1]-t2[1];
$result=str_pad(floor($d/60),2,'0',STR_PAD_LEFT).':'.str_pad($d%60,2,'0',STR_PAD_LEFT);

Вы можете сделать это вручную, отслеживая количество отработанных минут - это будет точно, а также позволит вам показать отрицательные различия.

<?php
// get the difference in H:mm between two H:mm 
function diff_time($actual, $expected) {
    $diff_mins = mins($actual) - mins($expected);

    return format_mins($diff_mins);
}

// convert a HH:mm to number of minutes
function mins($t) {
    $parts = explode(':', $t);

    return $parts[0] * 60 + $parts[1];
}

// convert number of minutes into HH:mm
function format_mins($m) {
    $mins = $m % 60;
    $hours = ($m - $mins) / 60;

    // format HH:mm
    return $hours . ':' . sprintf('%02d', abs($mins));
}

var_dump(diff_time('23:15', '25:45'));
var_dump(diff_time('25:15', '23:45'));

Это выводит:

string(5) "-2:30"
string(4) "1:30"

.. во-первых, на 2:30 меньше ожидаемого, для второго на 1:30 больше, чем ожидалось.

Другие вопросы по теме