Проблема преобразования времени Unix в человеческое время - PullRequest
0 голосов
/ 05 июня 2019

У меня есть онлайн-контроллер, где я хочу знать время безотказной работы и время последнего посещения моих точек доступа.для этого я использую метод epoch convert для преобразования времени unix в читаемое человеком время.

это код, который я использую

// getting controller ap info //

    $name=$status=$uptime=$last_seen=[];
foreach ($ligowave->result as $index => $obj) {
    $name[]      = $obj->name;
    $status[]    = $obj->status;
    $uptime[]    = $obj->uptime;
    $last_seen[] = $obj->last_seen;
}


// time settings //

$epoch = $uptime;
$uptimetime = (new DateTime("@$epoch"))->format(' H:i:s');

$epoch = $last_seen;
$lastseendate = (new DateTime("@$epoch"))->SetTimeZone(new DateTimeZone('Europe/Amsterdam'))->format(' d-m-Y H:i:s');

if ($status == "up") {
    echo $name;
    echo " is up, ";
    echo "uptime is:" . $uptimetime;
} else {
    echo $name;
    echo " is down, ";
    echo "device is last seen:" . $lastseendate;
}
return array($name, $status, $epoch, $uptimetime, $lastseendate);
}

полученная ошибка:

Неустранимая ошибка PHP: необработанное исключение: DateTime :: __ construct (): не удалось проанализировать строку времени (@Array) в позиции 0 (@): неожиданный символ

Ответы [ 2 ]

1 голос
/ 05 июня 2019

Обратите внимание:

Этот ответ только о разрешении конкретной ошибки PHP, как указано в вопросе. Более широкий ответ о том, как эффективно написать код для итерации по массивам, см. В ответе Фрая .

Полученная вами ошибка:

Неустранимая ошибка PHP: необработанное исключение: DateTime :: __ construct (): не удалось проанализировать строку времени (@Array) в позиции 0 (@): неожиданный символ

Что на самом деле не так и почему?

1) У вас есть неперехваченное исключение, которое приводит к фатальной ошибке из-за того, что он неуязвим. Исключения являются центральными для объектного программирования и должны быть исследованы и реализованы в ваших PHP-скриптах.

2) Почему у вас есть исключение в первую очередь? В сообщении об ошибке указывается, что исключение вызвано «Не удалось разобрать строку времени (@Array)». Итак, вы пытаетесь присвоить объекту DateTime массив , когда он ожидает строку . Это поможет вам Прочтите PHP DateTime __construct Страница руководства .

3) Кроме того, более конкретно, символ @ является неожиданным; что означает, что это не должно быть там. Этот символ действителен только в том случае, если за ним следуют отметка времени целочисленные значения в формате строка .

Поскольку массив выводится в виде строки (т. Е. В кавычках), конечным результатом является "@Array", поэтому @ буквально воспринимается DateTime; но, конечно, этот символ не ожидается DateTime в любой нечисловой строке входящего времени. Это коренная причина вашей фатальной ошибки здесь.

Несмотря на то, что PHP в некоторой степени использует свободную приведение типов, завершение массива $var в кавычки слишком далеко слишком потеря, поэтому массив просто выводит «Array» и выдает соответствующее уведомление PHP:

Примечание : преобразование массива в строку в .....

Чтобы получить правильный список строковых форматов DateTime для данного объекта, вы можете просмотреть эту страницу из руководства по PHP .

4) Я не понимаю, зачем вам эти внешние скобки?

Итак, как это сделать?

Чтение выпусков в обратном порядке с 4 до 1; правильный способ устранения этой конкретной ошибки:

  • Оберните попытку в блок try / catch, чтобы избежать этих фатальных ошибок.
  • Убедитесь, что значение, присвоенное объекту DateTime, является строкой
  • Удалите ненужные и недопустимые символы из этой строки.

Итак:

$epoch = $uptime;

try{ 
     /***
      * Uptime appears to be a numeric array of time string values 
      * Therefore go for the first one. 
      * You may want to wrap this code in a loop to catch each one.  
      ***/
     $uptimeTime = new DateTime("@".(string)$epoch[0]);
}
catch (Exception $ex){
    /***
     * If you wish to ignore these errors simply leave this block empty
     ***/
    error_log("There was a problem on line ".__LINE__."! ".print_r($ex));
}
/***
 * By default UTC timestamps are not zoned.   
 ***/
// $uptimeTime->setTimeZone(new DateTimeZone('Europe/Amsterdam'));

$uptimeTimeOutput = $uptimeTime->format('H:i:s');
/***
 * $uptimeTimeOutput is the correctly formatted date from $epoch[0]
 ***/
 print $uptimeTimeOutput; 

Я надеюсь, что с помощью приведенной выше информации вы сможете самостоятельно исправить второй DateTime код (например, строку new DateTime). :-)

TL; DR

Пожалуйста, прочитайте Руководство по PHP и позвольте ему информировать вас о выборе кода.

1 голос
/ 05 июня 2019

Основная проблема вызвана определением $uptime[] как массива значений, в результате чего $epoch = $uptime содержит массив строк меток времени.Когда DateTime() ожидает единственное значение string.

Для решения проблемы необходимо переместить вызовы DateTime внутри итерации foreach.

Другая проблема, какв ответе Мартина упоминается, что вы не обрабатываете исключения в своем коде.Если uptime или last_seen не соответствует ожидаемому значению, которое передается конструктору DateTime, будет выдано исключение.

Для обработки исключений вы можете использовать блок try/catch вЧтобы решить проблему, которая возникает в вашем коде.Исключения предназначены для указания на фатальные ошибки в вашем коде, так что вы можете разрешать или проверять их программно и, как правило, не должны игнорироваться с помощью try/catch.Для получения более подробной информации, пожалуйста, смотрите https://www.php.net/manual/en/language.exceptions.php

Не зная точно, что вы пытаетесь достичь с помощью своего кода.Похоже, вы хотите echo и return все значений от $ligowave->result.Я внес соответствующие изменения ниже, чтобы отразить ваши намерения.Наряду с некоторыми незначительными упрощениями.

Пожалуйста, уточните, что вы хотите return и echo, и я уточню свой ответ.

Пример: https://3v4l.org/O0nS6

   //...

    // getting controller ap info //

        $values = [];
        foreach ($ligowave->result as $index => $obj) {
            //convert the unix timestamps to DateTime objects
            $uptime = (new DateTime('@' . $obj->uptime));
            $last_seen = (new DateTime('@' . $obj->last_seen))->setTimeZone(new DateTimeZone('Europe/Amsterdam'));

            //store the return values into an array
            $values[] = $value = [
                'name' => $obj->name,
                'status' => $obj->status,
                'uptimetime' => $uptime->format('H:i:s'),
                'lastseendate' => $last_seen->format('d-m-Y H:i:s')
            ];

            //output each of the statuses
            printf('%s is %s, ', $obj->name, $obj->status);
            if ('up' === $obj->status) {
                echo 'uptime is: ' . $value['uptimetime'];
            } else {
                echo 'device is last seen: ' . $value['lastseendate'];
            }
        }

        return $values;
}

Результат:

foo is up, uptime is: 10:20:54
bar is down, device is last seen: 01-06-2019 08:22:30

Возвраты:

array (
  0 => 
  array (
    'name' => 'foo',
    'status' => 'up',
    'uptimetime' => '10:20:54',
    'lastseendate' => '05-06-2019 11:16:21',
  ),
  1 => 
  array (
    'name' => 'bar',
    'status' => 'down',
    'uptimetime' => '10:20:54',
    'lastseendate' => '01-06-2019 08:22:30',
  ),
)

Похоже, что вы используете 24 часавремя, чтобы представить продолжительность.В этом случае вам нужно будет использовать DateInterval вместо DateTime, используя DateTime::diff с соответствующего периода времени.Для получения более подробной информации см. https://php.net/manual/en/class.dateinterval.php

Предполагая, что uptime - это время запуска, а last_seen - текущее время выполнения, вы можете использовать $uptime->diff($last_seen), чтобы получить время, которое прошло между uptime иlast_seen (продолжительность) вместо значения времени 24 часа uptime.В противном случае вы можете использовать $uptime->diff(new DateTime('now', new DateTimeZone('Europe/Amsterdam'))), чтобы использовать текущую дату и время.

Одно предостережение, что часы DateInterval не кумулятивны, то есть вам нужно каким-то образом добавлять дни.Я использовал самый точный из %a в отличие от добавления к часам с days * 24

Пример: https://3v4l.org/LHdqL

//...

$uptime = (new DateTime('@' . $obj->uptime))->setTimeZone(new DateTimeZone('Europe/Amsterdam'));
$last_seen = (new DateTime('@' . $obj->last_seen))->setTimeZone(new DateTimeZone('Europe/Amsterdam'));
$values[] = $value = [
    'name' => $obj->name,
    'status' => $obj->status,
    'lastseendate' => $last_seen->format('d-m-Y H:i:s'),
    'uptimetime' => $uptime->diff($last_seen)->format('%a.%H:%I:%S'), //DD.HH:MM:SS
];

//...

Результат:

foo is up, uptime is: 12.22:48:26
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...