Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get file mtime with millisecond resolution from Java

When I read the mtime of a file from Java using Files.getLastModifiedTime, the return value is truncated to whole seconds. I know this works on other systems to get mtimes with millisecond resolution, so what could be different about mine?

Here is a complete standalone test which compiles and runs:

import java.nio.file.attribute.FileTime;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Test {
  public static void main(String[] args) throws java.io.IOException {
    FileTime timestamp = Files.getLastModifiedTime(Paths.get("/tmp/test"));
    System.out.println(timestamp.toMillis());
  }
}

The output is (with my particular test file) 1405602038000, whereas ls shows:

$ ls --full-time /tmp/test                                                                                                                                                                                                    
-rw-rw-r-- 1 daniel daniel 0 2014-07-17 16:00:38.413008992 +0300 /tmp/test

I would expect the Java output to be 1405602038413.

I'm running on Linux with ext4. I tried both openjdk 1.7 and Oracle jdk 1.8.

like image 889
danarmak Avatar asked Jul 17 '14 13:07

danarmak


2 Answers

The ability to get file timestamps on *nix systems with higher precision was added in Java 8 by this commit, however, on the native side, it requires POSIX 2008 compliance:

#if (_POSIX_C_SOURCE >= 200809L) || defined(__solaris__)
    (*env)->SetLongField(env, attrs, attrs_st_atime_nsec, (jlong)buf->st_atim.tv_nsec);
    (*env)->SetLongField(env, attrs, attrs_st_mtime_nsec, (jlong)buf->st_mtim.tv_nsec);
    (*env)->SetLongField(env, attrs, attrs_st_ctime_nsec, (jlong)buf->st_ctim.tv_nsec);
#endif

And, apparently, the Java build you are using doesn't set it, so nanoseconds part of the timestamp is not available and stays zero.

like image 130
izstas Avatar answered Sep 22 '22 09:09

izstas


I looked at the source code:

In the Java 7 case, the method gives the last modified timestamp with 1 second precision:

  • http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/nio/fs/UnixFileAttributes.java#UnixFileAttributes.lastModifiedTime%28%29

In the Java 8 case, it looks like it should give microsecond precision:

  • http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/sun/nio/fs/UnixFileAttributes.java#UnixFileAttributes.lastModifiedTime%28%29

But in either case, the code doesn't seem to provide a way to get the timestamp with a different precision.

like image 38
Stephen C Avatar answered Sep 21 '22 09:09

Stephen C