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?
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");
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.
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";
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With