I have a method in a class, which checks if a file is older than a day. It achieves this by getting the last change date of the file and comparing it with “now”:
private function checkFileOutdated(string $filePath): bool { if (file_exists($filePath)) { $fileTimeStamp = filectime($filePath); $now = new DateTimeImmutable(); $fileDate = new DateTimeImmutable('@' . $fileTimeStamp); $diff = (int) $now->format('Ymd') - (int) $fileDate->format('Ymd'); return $diff > 0; } return true; }
I want to write a Unittest faking an outdated file. I tried to change the file date with touch:
$location = '/var/www/var/xls/myfile.xlsx'; $handle = fopen($location, 'wb'); fclose($handle); exec('touch -a -m -t 202109231158 ' . $location); exec('ls -hl ' . $location, $output); var_dump($output);
The output gives me the information that in fact my file is from “Sep 23 11:58”, Yeay…..
But my test is failing and when I debug my file date is today and not September, the 23rd.
Using filemtime results in the same.
Is it possible to fake a file timestamp?
My system runs on an alpine linux.
Advertisement
Answer
Note you don’t have to create the file first, because touch does that for you. And there is a PHP built-in for touch()
, you don’t have to shell exec:
touch('/tmp/foo', strtotime('-1 day')); echo date('r', fileatime('/tmp/foo')), "n"; echo date('r', filectime('/tmp/foo')), "n"; echo date('r', filemtime('/tmp/foo')), "n";
This yields:
Tue, 02 Nov 2021 12:18:17 -0400 Wed, 03 Nov 2021 12:18:17 -0400 Tue, 02 Nov 2021 12:18:17 -0400
Applying your code but with filemtime
:
$fileTimeStamp = filemtime($filePath); $now = new DateTimeImmutable(); $fileDate = new DateTimeImmutable('@' . $fileTimeStamp); $diff = (int) $now->format('Ymd') - (int) $fileDate->format('Ymd'); var_dump($diff);
Yields the desired truthy value:
1
However, this is a rather roundabout comparison. I’d just compare the timestamp values directly:
return filemtime('/tmp/foo') <= strtotime('-1 day');