Вопрос по php – Странное поведение PHP time math: почему strtotime () возвращает отрицательные числа?

2

Я пытаюсь сделать некоторую очень основную математику времени - в основном, учитывая ввод времени и расстояния, вычислить скорость. Я решил использовать strtotime () для преобразования входных значений времени в секунды, но получаю некоторые странные результаты.

Например, учитывая этот пример программы:

<?php
$t1 = strtotime("3:15:00",0);
$t2 = strtotime("1:00:00",0);
$t3 = strtotime("2:00:00",0);
$t4 = strtotime("9:00:00",0);

echo $t1 . "\n";
echo $t2 . "\n";
echo $t3 . "\n";
echo $t4 . "\n";
?>

Почему я получаю эти результаты?

$ php test.php 
-56700
-64800
-61200
-36000

Update:

Поскольку никто не сказал этого явно, позвольте мне объяснить ошибку в вышеупомянутой функции. Я предполагал, что передача нулевого времени в strtotime () приведет к тому, что он сгенерирует метки времени, полученные от полуночи 31.12.1969 UTC - что звучит странно, но сработает для моих целей.

На что я не рассчитывал, так это то, что strtotime () учитывает часовые пояса при преобразовании строк, и мой сервер, по-видимому, на 5 часов отстает от UTC. Кроме того, из-за сдвига часового пояса, PHP интерпретирует время какthe day before the epoch что означает, что он интерпретирует мои времена как происходящие по отношению к декабрю30th1969 вместо 31-го, что приводит к отрицательным числам ...

Похоже, что Евгений прав: если я хочу вычислить только истекшее время, я не могу использовать встроенные функции времени.

Если, конечно, все времена неявно относятся к 0, но я "читаю ваши требования как" время ввода дня " (абсолютное время), а не «прошедшее время». deceze♦
Так? Выare Преобразование строк в секунды с помощью strtotime (), только с добавлением всех секунд, начиная с 1970 года. Если вы выполняете только относительные вычисления между этими временными метками, это не имеет значения. 0, 900, 1345 или 1246399668, 1246400568, 1246401013 - оба одинаковые относительные отношения. deceze♦
«Если я хочу рассчитать только истекшее время, я не могу использовать встроенные функции времени». - Нет, вы можете просто пропустить второй параметр для strtotime (). Вы получите временную метку на сегодня с указанным вами временем суток, часовые пояса не будут иметь большого значения. Вы только провоцируете крайний случай, указав 0 в качестве второго параметра. deceze♦
Это бессмысленно. Опять же - мне не нужно абсолютное время, мне нужно преобразовать введенную пользователем строку в секунды. Единственное, как будет работать ваше решение, - это сделать что-то вроде strtotime («пользовательская строка», time ()) - strtotime («полночь», time ()); Mike Heinz
... У меня есть расстояние и время, и я хочу рассчитать скорость. Как в расстоянии / времени, вы знаете? Я продолжаю говорить, что это время не абсолютное время. Разделение расстояния на количество секунд с 1970 года не даст полезного числа! Mike Heinz

Ваш Ответ

5   ответов
0

strtotime() без второго аргумента получает время из предоставленной строки и заполняет пробелы с текущей даты:

echo date('Y-m-d H:i:s', strtotime("3:15:00"));
-> 2009-06-30 03:15:00

Со вторым аргументом он вычисляет дату относительно второго аргумента:

echo date('Y-m-d H:i:s', strtotime("3:15:00", 0));
-> 1970-01-01 03:15:00

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

echo strtotime("3:15:00") - strtotime("3:00:00");
-> 900

Изменить: Конечно, принимая во внимание, что это большее число:

$t1 = strtotime("3:15:00");
$t2 = strtotime("3:30:00");

$diff = max($t1, $t2) - min($t1, $t2);
$diff = abs($t1 - $t2);

Или что-то в этом роде ...

0

Попробуйте это без второго параметра. Предполагается, что это будет метка времени для возвращаемого времени, относительно которого. Задание 0 означает, что вы запрашиваете метку времени относительно эпохи Unix.

В ответ на ваш комментарий:

Это не документированная функциональность, но я используюstrtotime("HH:MM") все время, и он возвращает отметку времени относительно текущего времени. Я думаю, если вы хотите быть уверены, вы могли бы сделать это:

strtotime("3:15:00",time());
Error: User Rate Limit Exceeded Mike Heinz
Error: User Rate Limit Exceeded Mike Heinz
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Mike Heinz
2

Видимо, с просто непростыми временами PHP назначает дату 31 декабря 1969 года. Когда я запустил это:

echo date('F j, Y H:i:s', $t1) . "\n";
echo date('F j, Y H:i:s', $t2) . "\n";
echo date('F j, Y H:i:s', $t3) . "\n";
echo date('F j, Y H:i:s', $t4) . "\n";

Я получил это:

December 31, 1969 03:15:00
December 31, 1969 01:00:00
December 31, 1969 02:00:00
December 31, 1969 09:00:00

Помни чтоstrtotime возвращает метку времени UNIX, которая определяется как количество секунд с 1 января 1970 года. По определению метка времени UNIX относится к определенному месяцу / дню / году, поэтому, несмотря на названиеstrtotime на самом деле не предназначен для голых времен без дат.

Error: User Rate Limit Exceeded Mike Heinz
5

Если вы хотите сделать что-то подобное, я думаю, что вы хотите просто сделать некоторые математические расчеты для самих строк времени и преобразовать их в количество секунд, например:

<?php
function hmstotime($hms)
{
    list($hours, $minutes, $seconds) = explode(":",$hms);
    return $hours * 60 * 60 + $minutes * 60 + $seconds;
}
?>
Error: User Rate Limit Exceeded Mike Heinz
Error: User Rate Limit Exceeded
1

Потому что strtotime () выводит количество секунд относительно второго аргумента (в вашем случае эпоха Unix (31 декабря 1969 г. 19:00:00)).

Ожидаются отрицательные числа, потому что «3: 15: 00» 56700 секунд до эпохи Unix.

Error: User Rate Limit Exceeded Mike Heinz

Похожие вопросы