Время модификации файла PHP в миллисекундах

Я там, сейчас я пишу модульный тест, который утверждает, что файл не был изменен. Выполнение тестового кода занимает менее одной секунды, и поэтому я хотел бы знать, можно ли получить время модификации файла в миллисекундах. Функция filemtime() возвращает метку времени UNIX в секундах.

В моем текущем решении используется функция sleep(1), которая гарантирует, что прошла 1 секунда, прежде чем проверять, была ли она изменена или нет. Мне не нравится это решение, так как оно сильно замедляет тест.

Я не могу утверждать равенство содержимого с помощью get_file_contents(), поскольку данные, которые можно перезаписать, будут одинаковыми.

Я предполагаю, что это невозможно, не так ли?


person Steven Rosato    schedule 27.05.2010    source источник


Ответы (5)


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

Кстати, обратите внимание, что PHP кэширует возвращаемое значение filemtime() внутренне, поэтому clearstatcache() должен быть вызван раньше.

Альтернативный метод может состоять в том, чтобы сначала изменить (или удалить) содержимое файла, чтобы вы могли легко идентифицировать изменения. Поскольку состояние системы должно оставаться неизменным после выполнения каждого теста, в любом случае имеет смысл восстановить исходное содержимое файла после выполнения модульного теста.

person nuqqsa    schedule 28.05.2010
comment
Мне нравится эта идея, я предпочитаю манипулировать контентом, чем спать в течение 1 секунды, что намного быстрее. Спасибо за чаевые. - person Steven Rosato; 28.05.2010

function getTime($path){
    clearstatcache($path);
    $dateUnix = shell_exec('stat --format "%y" '.$path);
    $date = explode(".", $dateUnix);
    return filemtime($path).".".substr($date[1], 0, 8);
}

получить время("мой файл");

person Eliasz Kubala    schedule 27.11.2013

Попробуйте эту простую команду:

ls --full-time 'filename'

и вы можете видеть, что точность временной метки файла не вторая, она более точная. (используя Linux, но не думаю, что это отличается в Unix), но я до сих пор не знаю функции PHP для получения точной метки времени, возможно, вы сможете проанализировать результат системного вызова.

person Balu    schedule 09.03.2012

Если файловая система ext4 (распространена в более поздних версиях unix/linux, таких как Ubuntu) или ntfs (Windows), то mtime имеет точность менее секунды.

Если файловая система ext3 (или, возможно, другая; это было стандартом некоторое время назад и до сих пор используется RHEL), то mtime сохраняется только с точностью до секунды. Возможно, именно из-за этого старого значения по умолчанию PHP поддерживает только mtime с точностью до секунды.

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

(Я протестировал следующее в системе только с английской локалью; «удобочитаемый» вывод stat может отличаться, или поведение strtotime может отличаться в неанглийских локалях. Он должен нормально работать в любом часовом поясе, так как вывод stat включает спецификатор часового пояса, который учитывается strtotime.)

class FileModTimeHelper
{
    /**
     * Returns the file mtime for the specified file, in the format returned by microtime()
     *
     * On file systems which do not support sub-second mtime precision (such as ext3), the value
     * will be rounded to the nearest second.
     *
     * There must be a posix standard "stat" on your path (e.g. on unix or Windows with Cygwin)
     *
     * @param $filename string the name of the file
     * @return string like microtime()
     */
    public static function getFileModMicrotime($filename)
    {
        $stat = `stat --format=%y $filename`;
        $patt = '/^(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)\.(\d+) (.*)$/';
        if (!preg_match($patt, $stat, $matches)) {
            throw new \Exception("Unrecognised output from stat. Expecting something like '$patt', found: '$stat'");
        }
        $mtimeSeconds = strtotime("{$matches[1]} {$matches[3]}");
        $mtimeMillis = $matches[2];
        return "$mtimeSeconds.$mtimeMillis";
    }
}
person Rich    schedule 30.09.2013
comment
(Было бы безопаснее избегать вызова 'strtotime', используя, например, 'stat --format="%Y %y" $filename', но я написал эту версию сейчас.) - person Rich; 30.09.2013

Хм. Представьте себе веб-сервер, на котором мы используем комбинацию PHP и, например, nodeJS. В nodeJS, когда мы получаем время модификации файла, оно включает миллисекунды. В PHP этого нет. Теперь предположим, что для любых больших файлов (много гигабайт), которые мы позволяем пользователю загружать, у нас есть и поддерживается соответствующий файл, содержащий предварительно рассчитанную контрольную сумму MD5 для всего файла. Мы сохраняем эту контрольную сумму в файле с тем же именем, что и исходный файл, но с добавлением размера и времени модификации файла. ВКЛЮЧАЯ МИЛЛИСЕКУНДЫ! (все это делается узлом)

Пример: GEBCO_2019.nc (11723617646 байт) и GEBCO_2019.nc.11723617646-2019-10-31T15-03-06.687Z.md5.

Теперь на странице загрузок мы решаем отобразить контрольную сумму MD5. Это использует PHP-код.

OH NO!!!

Мы вызываем filemtime, но, увы, мы не можем получить миллисекунды, поэтому мы не можем определить имя файла Md5.

МЫ МОГЛИ ИЗМЕНИТЬ КОД УЗЛА, чтобы игнорировать миллисекундную часть.

Это похоже на то, что недостаток PHP здесь заставляет нас выбирать меньший общий знаменатель, чем мы должны были бы.

Также исключительно УЖАСНО прибегать к запуску внешней программы только для того, чтобы получить время модификации файла. Если бы вам пришлось делать это 50 или 60 раз для загрузки одной страницы, я ожидаю, что это немного замедлит работу!!!

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

person Dave Hussey    schedule 22.11.2019