dir-spooler-protolib/src/main/java/com/streamsets/pipeline/lib/dirspooler/SpoolDirUtil.java
public static boolean compareFiles(WrappedFileSystem fs, WrappedFile f1, WrappedFile f2) {
    if (!fs.exists(f2)) {
      return true;
    }

    try {
      long mtime1 = fs.getLastModifiedTime(f1);
      long mtime2 = fs.getLastModifiedTime(f2);

      long ctime1 = fs.getChangedTime(f1);
      long ctime2 = fs.getChangedTime(f2);

      long time1 = Math.max(mtime1, ctime1);
      long time2 = Math.max(mtime2, ctime2);

      int compares = Long.compare(time1, time2);

      if (compares != 0) {
        return compares > 0;
      }
    } catch (IOException ex) {
      LOG.error("Failed to get ctime: '{}'", f1.getFileName(), ex);
      return false;
    }

    return f1.getAbsolutePath().compareTo(f2.getAbsolutePath()) > 0;
  }
public static boolean compareFiles(WrappedFileSystem fs, WrappedFile f1, WrappedFile f2) {
    if (!fs.exists(f2)) {
      return true;
    }

    try {
      long mtime1 = fs.getLastModifiedTime(f1);
      long mtime2 = fs.getLastModifiedTime(f2);

      long ctime1 = fs.getChangedTime(f1);
      long ctime2 = fs.getChangedTime(f2);

      long time1 = Math.max(mtime1, ctime1);
      long time2 = Math.max(mtime2, ctime2);

      int compares = Long.compare(time1, time2);

      if (compares != 0) {
        return compares > 0;
      }
    } catch (IOException ex) {
      LOG.error("Failed to get ctime: '{}'", f1.getFileName(), ex);
      return false;
    }

    return f1.getAbsolutePath().compareTo(f2.getAbsolutePath()) > 0;
  }
True if f1 is "newer" than f2.