Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP file modification time in milliseconds

Tags:

php

filemtime

I there, I am currently writing a unit test which asserts that a file did not get modified. The test code execution takes less than one second and therefore I would like to know if it is possible to retrieve the file modification time in milliseconds. filemtime() function returns the UNIX timestamp in seconds.

My current solution is using the sleep(1) function which will assure me that 1 second passed before checking if it was modified or not. I don't like that solution since it slows down the test by a great deal.

I cannot assert the content equality via get_file_contents() since the data that can be rewritten would be the same.

I am guessing it is impossible, is it?

like image 457
Steven Rosato Avatar asked May 27 '10 18:05

Steven Rosato


4 Answers

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

getTime("myFile");

like image 155
Eliasz Kubala Avatar answered Nov 07 '22 16:11

Eliasz Kubala


Try this simple command:

ls --full-time 'filename'

and you can see the file timestamp precision is not second, it is more precise. (using Linux, but don't think it differs in Unix) but I still don't know of a PHP function for getting precise timestamp, maybe you can parse the result of the system call.

like image 21
Balu Avatar answered Nov 07 '22 16:11

Balu


If the file system is ext4 (common on more recent unixes / linuxes like Ubuntu) or ntfs (Windows), then the mtime does have sub-second precision.

If the file system is ext3 (or perhaps others; this was the standard a while ago and is still used by RHEL), then the mtime is only stored to the nearest second. Perhaps that old default is why PHP only supports mtime to the nearest second.

To fetch the value in PHP, you need to call an external util, since PHP itself does not support it.

(I have tested the following on a system with an English locale only; the "human readable" output of stat may differ, or the strtotime behaviour may differ on non-English locales. It should work fine in any timezone, as the output of stat includes a timezone specifier which is honoured by 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";
    }
}
like image 3
Rich Avatar answered Nov 07 '22 14:11

Rich


AFAIK UNIX timestamp's precision is seconds, so this may not be a possibility.

BTW, note that PHP caches the return value of filemtime() internally, thus clearstatcache() should be called before.

An alternative method could be to modify (or delete) the contents of the file first so that you can easily identify changes. Since the state of the system should remain the same after each test is executed, it would make sense anyways to restore the original file contents after the unit test has run.

like image 2
nuqqsa Avatar answered Nov 07 '22 15:11

nuqqsa