InstantComparator.java

  1. /*
  2.  * Copyright (C) 2019, Thomas Wolf <thomas.wolf@paranor.ch> and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */
  10. package org.eclipse.jgit.treewalk;

  11. import java.time.Instant;
  12. import java.util.Comparator;

  13. /**
  14.  * Specialized comparator for {@link Instant}s. If either timestamp has a zero
  15.  * fraction, compares only seconds. If either timestamp has no time fraction
  16.  * smaller than a millisecond, compares only milliseconds. If either timestamp
  17.  * has no fraction smaller than a microsecond, compares only microseconds.
  18.  */
  19. class InstantComparator implements Comparator<Instant> {

  20.     @Override
  21.     public int compare(Instant a, Instant b) {
  22.         return compare(a, b, false);
  23.     }

  24.     /**
  25.      * Compares two {@link Instant}s to the lower resolution of the two
  26.      * instants. See {@link InstantComparator}.
  27.      *
  28.      * @param a
  29.      *            first {@link Instant} to compare
  30.      * @param b
  31.      *            second {@link Instant} to compare
  32.      * @param forceSecondsOnly
  33.      *            whether to omit all fraction comparison
  34.      * @return a value &lt; 0 if a &lt; b, a value &gt; 0 if a &gt; b, and 0 if
  35.      *         a == b
  36.      */
  37.     public int compare(Instant a, Instant b, boolean forceSecondsOnly) {
  38.         long aSeconds = a.getEpochSecond();
  39.         long bSeconds = b.getEpochSecond();
  40.         int result = Long.compare(aSeconds, bSeconds);
  41.         if (result != 0) {
  42.             return result;
  43.         }
  44.         int aSubSecond = a.getNano();
  45.         int bSubSecond = b.getNano();
  46.         if (forceSecondsOnly || (aSubSecond == 0)
  47.                 || (bSubSecond == 0)) {
  48.             // Don't check the subseconds part.
  49.             return 0;
  50.         } else if (aSubSecond != bSubSecond) {
  51.             // If either has nothing smaller than a millisecond, compare only
  52.             // milliseconds.
  53.             int aSubMillis = aSubSecond % 1_000_000;
  54.             int bSubMillis = bSubSecond % 1_000_000;
  55.             if (aSubMillis == 0) {
  56.                 bSubSecond -= bSubMillis;
  57.             } else if (bSubMillis == 0) {
  58.                 aSubSecond -= aSubMillis;
  59.             } else {
  60.                 // Same again, but for microsecond resolution. NTFS has 100ns
  61.                 // resolution, but WindowsFileAttributes may provide only
  62.                 // microseconds (1000ns). Similar for some Unix file systems.
  63.                 int aSubMicros = aSubSecond % 1000;
  64.                 int bSubMicros = bSubSecond % 1000;
  65.                 if (aSubMicros == 0) {
  66.                     bSubSecond -= bSubMicros;
  67.                 } else if (bSubMicros == 0) {
  68.                     aSubSecond -= aSubMicros;
  69.                 }
  70.             }
  71.         }
  72.         return Integer.compare(aSubSecond, bSubSecond);
  73.     }

  74. }