Get file created date in node
Asked Answered
T

6

16

In node I can get a file's modified date using the standard file stat object. Is there a way I can also find its created date? I can't find anything in the http://nodejs.org/api/fs.html#fs_class_fs_stats documentation at all.

Tello answered 9/7, 2013 at 15:19 Comment(2)
util.inspect(stats) should give you the information... What do you get as output of this?Higherup
3 date values - atime, ctime and mtime, none of which are the created time (ctime is the changed time)Tello
E
6

Whether or not you can get the file creation time depends on the OS and file system. Traditional POSIX only defines ctime, which is (rather confusingly), the inode modification date, not the creation date, as other people have mentioned. However, on some operating systems, you can get st_birthtimespec, or st_birthtime which is a true "create" time. You'll need to check sys/stat.h on your host operating system to see what, if anything, is available.

Unfortunately, whether or not you can access the entire stat structure from node.js is a different kettle of fish. But at least you can figure out if your OS even supports it and go from there.

2019 Update:

You can always access this property, but on many file systems it will be wrong. According to the Node.js docs:

On filesystems where birthtime is not available, this field may instead hold either the ctime or 1970-01-01T00:00Z (ie, Unix epoch timestamp 0). This value may be greater than atime or mtime in this case. On Darwin and other FreeBSD variants, also set if the atime is explicitly set to an earlier value than the current birthtime using the utimes(2) system call. https://nodejs.org/api/fs.html#fs_stats_birthtimems

Etom answered 10/7, 2013 at 11:28 Comment(8)
@fraber clearly the OP thinks I solved his problem, so I'm not certain what your grounds for complaint is. He didn't need help understanding JS, he needed to understand the file system underpinnings. if the question was "what JS call is necessary to access file system stat structures", I'd agree with you, but that's not what he asked.Etom
I appreciate your detailed technical knowledge, but I believe this guy (the same way as I) just needed a simple solution to get he creation date. The answer below from Flaky provides it...Basseterre
@Basseterre the answer below is incomplete though. It will only work for some users. A lot of Unix users are using filesystems on which this value is not available. For them the birthtime will be set to the modified time. If you plan on making anything that can be used by multiple people without restricting their file system, you cannot use Flaky's answer.Fingerbreadth
is this still the case 2019?Snippy
@BugWhisperer this is still the case. For a fairly up-to-date list of which file systems do/don't support creation time, look here: unix.stackexchange.com/questions/7562/…Etom
so the birthtimeMs and birthtime properties of a Stats object won't reflect the creation date in any POSIX system? if so, what value is returned for those properties?Snippy
@BugWhisperer According to the Node.js docs, "On filesystems where birthtime is not available, this field may instead hold either the ctime or 1970-01-01T00:00Z (ie, Unix epoch timestamp 0). This value may be greater than atime or mtime in this case. On Darwin and other FreeBSD variants, also set if the atime is explicitly set to an earlier value than the current birthtime using the utimes(2) system call." Source: (nodejs.org/api/fs.html#fs_stats_birthtimems)Etom
yeah but is there any way to determine, for instance, which linux distros will have the stand in and which one?Snippy
S
28

If someone stumbles over this after all this time, as of Node v0.12.0 use this:

fs.stat(path, callback)

Where callback has two args err & stats. Stats object has property

birthtime

which is creation date.

Link to node api documentation link

Scheers answered 5/3, 2015 at 19:28 Comment(1)
Does not work on every file systems. Most Unix users won't have access to it. Ok to use in a script if it's available for you, but do not use in applications that you intend to make available to multiple users.Fingerbreadth
E
6

Whether or not you can get the file creation time depends on the OS and file system. Traditional POSIX only defines ctime, which is (rather confusingly), the inode modification date, not the creation date, as other people have mentioned. However, on some operating systems, you can get st_birthtimespec, or st_birthtime which is a true "create" time. You'll need to check sys/stat.h on your host operating system to see what, if anything, is available.

Unfortunately, whether or not you can access the entire stat structure from node.js is a different kettle of fish. But at least you can figure out if your OS even supports it and go from there.

2019 Update:

You can always access this property, but on many file systems it will be wrong. According to the Node.js docs:

On filesystems where birthtime is not available, this field may instead hold either the ctime or 1970-01-01T00:00Z (ie, Unix epoch timestamp 0). This value may be greater than atime or mtime in this case. On Darwin and other FreeBSD variants, also set if the atime is explicitly set to an earlier value than the current birthtime using the utimes(2) system call. https://nodejs.org/api/fs.html#fs_stats_birthtimems

Etom answered 10/7, 2013 at 11:28 Comment(8)
@fraber clearly the OP thinks I solved his problem, so I'm not certain what your grounds for complaint is. He didn't need help understanding JS, he needed to understand the file system underpinnings. if the question was "what JS call is necessary to access file system stat structures", I'd agree with you, but that's not what he asked.Etom
I appreciate your detailed technical knowledge, but I believe this guy (the same way as I) just needed a simple solution to get he creation date. The answer below from Flaky provides it...Basseterre
@Basseterre the answer below is incomplete though. It will only work for some users. A lot of Unix users are using filesystems on which this value is not available. For them the birthtime will be set to the modified time. If you plan on making anything that can be used by multiple people without restricting their file system, you cannot use Flaky's answer.Fingerbreadth
is this still the case 2019?Snippy
@BugWhisperer this is still the case. For a fairly up-to-date list of which file systems do/don't support creation time, look here: unix.stackexchange.com/questions/7562/…Etom
so the birthtimeMs and birthtime properties of a Stats object won't reflect the creation date in any POSIX system? if so, what value is returned for those properties?Snippy
@BugWhisperer According to the Node.js docs, "On filesystems where birthtime is not available, this field may instead hold either the ctime or 1970-01-01T00:00Z (ie, Unix epoch timestamp 0). This value may be greater than atime or mtime in this case. On Darwin and other FreeBSD variants, also set if the atime is explicitly set to an earlier value than the current birthtime using the utimes(2) system call." Source: (nodejs.org/api/fs.html#fs_stats_birthtimems)Etom
yeah but is there any way to determine, for instance, which linux distros will have the stand in and which one?Snippy
G
2

If you are using Linux then this information is not accessible (though it is stored in Ext4 file system). Thus fs.stat only returns atime, ctime, mtime values.

Generative answered 9/7, 2013 at 15:25 Comment(5)
ctime, according to everything else I've read, is changed time, which is similar, though not quite identical to modified timeTello
Unfortunately, you're right (I thought ctime was for creation time). I'll try some stuff, though, I'm gonna delete this if I won't find answer.Generative
Take a look at this: get file creation timeGenerative
is this still the case in 2019?Snippy
I suppose it is. It depends on OS/filesystem, which probably still works the same way.Generative
M
1

Here's a solution that worked well for me on both Linux and macOS (sorry Windows users).

It's a module you can import into your other code that uses Node's util.exec() method to pass a UNIX command, as a child process, and returns a UNIX timestamp string converted into an integer.

It will return null if the child process fails:

const util = require("util");
const exec = util.promisify(require("child_process").exec);

const executeCommand = async (cmd) => {
  try {
    return await exec(cmd, { timeout: 2000 }).then(async ({ stdout, stderr }) => {
      if (stderr) {
        return null;
      }
      if (stdout) {
        return stdout;
      }
    });
  } catch (cmdErr) {
    return null;
  }
};

exports.getFileDate = async (filePath) => {
  try {
    let cmd = ``;
    if (process.platform === "linux") {
      cmd = `stat -c %Y "${filePath}"`;
    } else if (process.platform === "darwin") {
      cmd = `stat -s "${filePath}"`;
    } else {
      console.error(`getFileDate() => Error: only 'linux' and 'darwin' platforms are supported`);
      return null;
    }

    let getDateResult = await executeCommand(cmd);
    if (getDateResult === null) {
      return null;
    }

    // Linux
    if (process.platform === "linux") {
      getDateResult = parseInt(getDateResult);
      return getDateResult;
    }

    // macOS
    else if (process.platform === "darwin") {
      // get the index where creation time starts
      let start = getDateResult.indexOf("st_ctime");

      // different timestamps are delimited by spaces
      let creationDate = getDateResult.substring(start, getDateResult.length);

      // parse the complete string to get 'st_ctime' value
      let splitResult = creationDate.split(" ");
      let timestamp = splitResult[0].replace("st_ctime=", "");

      // return 'null' if it's not a number
      if (isNaN(timestamp)) {
        return null;
      } else {
        timestamp = parseInt(timestamp);
        return timestamp;
      }
    }

    // catch errors
  } catch (err) {
    console.error(`getFileDate() => ${err}`);
    return null;
  }
};

Just import this new module into another script like so (assuming it's in the same directory):

const { getFileDate } = require("./getFileDate");

..and then you can pass a file path to the function call, and convert the UNIX timestamp into a readable date string like this:

let unixTimestamp = await getFileDate("path/to/some/file.txt");
let dateStr = new Date(unixTimestamp * 1000);
console.log(dateStr);
Monofilament answered 31/1, 2021 at 8:0 Comment(0)
B
0

I am using Fedora and there is no 'birthtime' field in the fs.stat result. But maybe you can try using node's child_process to invoke ls --full-time. At least on my machine it's giving me correct result.

fs.stat result:

{ dev: 64771,
  mode: 33279,
  nlink: 1,
  uid: 1000,
  gid: 1000,
  rdev: 0,
  blksize: 4096,
  ino: 2098445,
  size: 48523700,
  blocks: 94776,
  atime: Sat Jul 04 2015 19:01:29 GMT+1000 (AEST),
  mtime: Thu Aug 22 2013 16:45:10 GMT+1000 (AEST),
  ctime: Sat Jul 04 2015 19:01:29 GMT+1000 (AEST) }

ls --full-time

  -rwxrwxrwx. 1 pahuang pahuang 22M 2013-06-23 17:51:08.000000000 +1000 test_media/processed/20130621.mkv
Balliol answered 4/7, 2015 at 11:8 Comment(0)
P
0

node 18, typescript, dayjs:

    import fs from 'fs';
    import dayjs from 'dayjs';

    const stats: fs.Stats = fs.statSync($filename);
    const birthtime: string = dayjs(stats.birthtime).format('YYYY-MM-DD HH:mm');
Phosphorate answered 14/3 at 8:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.