fs: expose Stats times as Numbers

PR-URL: https://github.com/nodejs/node/pull/13173
Fixes: https://github.com/nodejs/node/issues/8276
Refs: https://github.com/nodejs/node/pull/12607
Refs: https://github.com/nodejs/node/pull/12818
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Brian White <mscdex@mscdex.net>
This commit is contained in:
Refael Ackermann 2017-05-23 12:15:56 -04:00
parent 324f1115b3
commit 47b9772f52
3 changed files with 59 additions and 30 deletions

View File

@ -301,10 +301,14 @@ argument to `fs.createReadStream()`. If `path` is passed as a string, then
## Class: fs.Stats ## Class: fs.Stats
<!-- YAML <!-- YAML
added: v0.1.21 added: v0.1.21
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/13173
description: Added times as numbers.
--> -->
Objects returned from [`fs.stat()`][], [`fs.lstat()`][] and [`fs.fstat()`][] and their Objects returned from [`fs.stat()`][], [`fs.lstat()`][] and [`fs.fstat()`][] and
synchronous counterparts are of this type. their synchronous counterparts are of this type.
- `stats.isFile()` - `stats.isFile()`
- `stats.isDirectory()` - `stats.isDirectory()`
@ -329,20 +333,23 @@ Stats {
size: 527, size: 527,
blksize: 4096, blksize: 4096,
blocks: 8, blocks: 8,
atimeMs: 1318289051000.1,
mtimeMs: 1318289051000.1,
ctimeMs: 1318289051000.1,
birthtimeMs: 1318289051000.1,
atime: Mon, 10 Oct 2011 23:24:11 GMT, atime: Mon, 10 Oct 2011 23:24:11 GMT,
mtime: Mon, 10 Oct 2011 23:24:11 GMT, mtime: Mon, 10 Oct 2011 23:24:11 GMT,
ctime: Mon, 10 Oct 2011 23:24:11 GMT, ctime: Mon, 10 Oct 2011 23:24:11 GMT,
birthtime: Mon, 10 Oct 2011 23:24:11 GMT } birthtime: Mon, 10 Oct 2011 23:24:11 GMT }
``` ```
Please note that `atime`, `mtime`, `birthtime`, and `ctime` are *Note*: `atimeMs`, `mtimeMs`, `ctimeMs`, `birthtimeMs` are [numbers][MDN-Number]
instances of [`Date`][MDN-Date] object and appropriate methods should be used that hold the corresponding times in milliseconds. Their precision is platform
to compare the values of these objects. For most general uses specific. `atime`, `mtime`, `ctime`, and `birthtime` are [`Date`][MDN-Date]
[`getTime()`][MDN-Date-getTime] will return the number of milliseconds elapsed object alternate representations of the various times. The `Date` and number
since _1 January 1970 00:00:00 UTC_ and this integer should be sufficient for values are not connected. Assigning a new number value, or mutating the `Date`
any comparison, however there are additional methods which can be used for value, will not be reflected in the corresponding alternate representation.
displaying fuzzy information. More details can be found in the
[MDN JavaScript Reference][MDN-Date] page.
### Stat Time Values ### Stat Time Values
@ -2841,6 +2848,7 @@ The following constants are meant for use with the [`fs.Stats`][] object's
[FS Constants]: #fs_fs_constants_1 [FS Constants]: #fs_fs_constants_1
[MDN-Date-getTime]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/getTime [MDN-Date-getTime]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/getTime
[MDN-Date]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date [MDN-Date]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date
[MDN-Number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type
[MSDN-Rel-Path]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#fully_qualified_vs._relative_paths [MSDN-Rel-Path]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#fully_qualified_vs._relative_paths
[Readable Stream]: stream.html#stream_class_stream_readable [Readable Stream]: stream.html#stream_class_stream_readable
[Writable Stream]: stream.html#stream_class_stream_writable [Writable Stream]: stream.html#stream_class_stream_writable

View File

@ -196,6 +196,10 @@ function Stats(
this.ino = ino; this.ino = ino;
this.size = size; this.size = size;
this.blocks = blocks; this.blocks = blocks;
this.atimeMs = atim_msec;
this.mtimeMs = mtim_msec;
this.ctimeMs = ctim_msec;
this.birthtimeMs = birthtim_msec;
this.atime = new Date(atim_msec + 0.5); this.atime = new Date(atim_msec + 0.5);
this.mtime = new Date(mtim_msec + 0.5); this.mtime = new Date(mtim_msec + 0.5);
this.ctime = new Date(ctim_msec + 0.5); this.ctime = new Date(ctim_msec + 0.5);

View File

@ -65,38 +65,55 @@ fs.open('.', 'r', undefined, common.mustCall(function(err, fd) {
assert.fail(err); assert.fail(err);
} }
if (stats) { if (stats) {
console.dir(stats);
assert.ok(stats.mtime instanceof Date); assert.ok(stats.mtime instanceof Date);
} }
fs.close(fd, assert.ifError); fs.close(fd, assert.ifError);
})); }));
console.log(`stating: ${__filename}`);
fs.stat(__filename, common.mustCall(function(err, s) { fs.stat(__filename, common.mustCall(function(err, s) {
assert.ifError(err); assert.ifError(err);
console.dir(s);
console.log(`isDirectory: ${JSON.stringify(s.isDirectory())}`);
assert.strictEqual(false, s.isDirectory()); assert.strictEqual(false, s.isDirectory());
console.log(`isFile: ${JSON.stringify(s.isFile())}`);
assert.strictEqual(true, s.isFile()); assert.strictEqual(true, s.isFile());
console.log(`isSocket: ${JSON.stringify(s.isSocket())}`);
assert.strictEqual(false, s.isSocket()); assert.strictEqual(false, s.isSocket());
console.log(`isBlockDevice: ${JSON.stringify(s.isBlockDevice())}`);
assert.strictEqual(false, s.isBlockDevice()); assert.strictEqual(false, s.isBlockDevice());
console.log(`isCharacterDevice: ${JSON.stringify(s.isCharacterDevice())}`);
assert.strictEqual(false, s.isCharacterDevice()); assert.strictEqual(false, s.isCharacterDevice());
console.log(`isFIFO: ${JSON.stringify(s.isFIFO())}`);
assert.strictEqual(false, s.isFIFO()); assert.strictEqual(false, s.isFIFO());
console.log(`isSymbolicLink: ${JSON.stringify(s.isSymbolicLink())}`);
assert.strictEqual(false, s.isSymbolicLink()); assert.strictEqual(false, s.isSymbolicLink());
const keys = [
assert.ok(s.mtime instanceof Date); 'dev', 'mode', 'nlink', 'uid',
'gid', 'rdev', 'ino', 'size',
'atime', 'mtime', 'ctime', 'birthtime',
'atimeMs', 'mtimeMs', 'ctimeMs', 'birthtimeMs'
];
if (!common.isWindows) {
keys.push('blocks', 'blksize');
}
const numberFields = [
'dev', 'mode', 'nlink', 'uid', 'gid', 'rdev', 'ino', 'size',
'atimeMs', 'mtimeMs', 'ctimeMs', 'birthtimeMs'
];
const dateFields = ['atime', 'mtime', 'ctime', 'birthtime'];
keys.forEach(function(k) {
assert.ok(k in s, `${k} should be in Stats`);
assert.notStrictEqual(s[k], undefined, `${k} should not be undefined`);
assert.notStrictEqual(s[k], null, `${k} should not be null`);
});
numberFields.forEach((k) => {
assert.strictEqual(typeof s[k], 'number', `${k} should be a number`);
});
dateFields.forEach((k) => {
assert.ok(s[k] instanceof Date, `${k} should be a Date`);
});
const jsonString = JSON.stringify(s);
const parsed = JSON.parse(jsonString);
keys.forEach(function(k) {
assert.notStrictEqual(parsed[k], undefined, `${k} should not be undefined`);
assert.notStrictEqual(parsed[k], null, `${k} should not be null`);
});
numberFields.forEach((k) => {
assert.strictEqual(typeof parsed[k], 'number', `${k} should be a number`);
});
dateFields.forEach((k) => {
assert.strictEqual(typeof parsed[k], 'string', `${k} should be a string`);
});
})); }));