Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

File timestamp resolution is inconsistent with fs.stat / fs.utimes #7000

Closed
RustyMarvin opened this issue Jan 30, 2014 · 3 comments
Closed

Comments

@RustyMarvin
Copy link

In node 0.11.11 under windows 7
the file timestamp resolution of fs.stat seems to be 1 millisecond, but if i try to set the timestamps, the resolution seems to be only 1 second. This is inconsistent.

> process.version
'v0.11.11'
> fs.writeFileSync('test.txt', 'abc');
undefined
> fs.statSync('test.txt').mtime.getTime();
1391100066267
> fs.utimesSync('test.txt', new Date(1356171132123), new Date(1356171132123));
undefined
> fs.statSync('test.txt').mtime.getTime();
1356171132000

In node 0.10 the resolution seems to be always 1 second.

> process.version
'v0.10.23'
> fs.writeFileSync('test.txt', 'abc');
undefined
> fs.statSync('test.txt').mtime.getTime();
1391100029000
> fs.utimesSync('test.txt', new Date(1356171132123), new Date(1356171132123));
undefined
> fs.statSync('test.txt').mtime.getTime();
1356171132000

I think the resolution should be either 1 second or 1 millisecond, but not mixed.
The timestamp resolution of the underlying windows filesystem NTFS is 100 nanoseconds, so both solutions would be fine ;-)

@tjfontaine
Copy link

So there are a couple of things here, first in v0.10 the precision of stat was only ever 1 second, that was changed for v0.11 branch in 51f128d after the integration for libuv.

The other issue you're having here, is that the interface for fs.utimes(path) actually implements utime() which only accepts second resolution.

On the other hand, if you were to use fs.futimes you would actually get subsecond precision

var fs = require('fs');

fs.writeFileSync('test.txt', 'abc');
console.log(fs.statSync('test.txt').mtime.getTime());
var a = new Date(1356171132123);
var b = new Date(1356171132321);
fs.utimesSync('test.txt', a, b);
console.log(fs.statSync('test.txt').mtime.getTime());
var fd = fs.openSync('test.txt', 'r+');
fs.futimesSync(fd, a, b);
console.log(fs.statSync('test.txt').mtime.getTime());
./node t.js
1391135755349
1356171132000
1356171132870

Huge caveat being that this requires filesystems to support subsecond resolution, which not all do -- of note HFS, ext[2,3], FAT.

ibobo added a commit to ibobo/gulp-preservetime that referenced this issue Aug 11, 2016
As stated here: nodejs/node-v0.x-archive#7000
utimes has 1 second resolution, whereas futimes has 1 microsecond resolution.
Since stat also has a 1 microsecond resolution, this caused conditional
builds (with gulp-newer for instance) to always rebuild files on
platforms with 1 microsecond timestamps for files (Linux with ext2/3).
@fcostarodrigo
Copy link

fcostarodrigo commented Sep 17, 2016

Could the documentation (It only says Integer) be improved to make this clear? It looks like I can pass new Date(), but Date.now() needs to be divided by 1000. According to MDN Date.prototype.valueOf() and Date.now() both return: "The number of milliseconds between 1 January 1970 00:00:00 UTC and the given date."

var fs = require('fs');

fs.writeFileSync('test.txt', 'abc');
console.log('    ok', fs.statSync('test.txt').atime.getTime());

fs.utimesSync('test.txt', new Date(), new Date());
console.log('    ok', fs.statSync('test.txt').atime.getTime());

console.log('    ok', Date.now());

fs.utimesSync('test.txt', Date.now(), Date.now());
console.log('not ok', fs.statSync('test.txt').atime.getTime());

fs.utimesSync('test.txt', Date.now() / 1000, Date.now() / 1000);
console.log('    ok', fs.statSync('test.txt').atime.getTime());

Output

    ok 1474133782000
    ok 1474133783000
    ok 1474133783702
not ok 1474133783702000
    ok 1474133783000

@cjihrig
Copy link

cjihrig commented Sep 17, 2016

This repo is largely abandoned. If you have issues with Node core, please report them at https://github.com/nodejs/node. If you're looking for general support, please head to https://github.com/nodejs/help.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants