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
12 import java.time.Instant;
13 import java.util.Comparator;
14
15 /**
16 * Specialized comparator for {@link Instant}s. If either timestamp has a zero
17 * fraction, compares only seconds. If either timestamp has no time fraction
18 * smaller than a millisecond, compares only milliseconds. If either timestamp
19 * has no fraction smaller than a microsecond, compares only microseconds.
20 */
21 class InstantComparator implements Comparator<Instant> {
22
23 @Override
24 public int compare(Instant a, Instant b) {
25 return compare(a, b, false);
26 }
27
28 /**
29 * Compares two {@link Instant}s to the lower resolution of the two
30 * instants. See {@link InstantComparator}.
31 *
32 * @param a
33 * first {@link Instant} to compare
34 * @param b
35 * second {@link Instant} to compare
36 * @param forceSecondsOnly
37 * whether to omit all fraction comparison
38 * @return a value < 0 if a < b, a value > 0 if a > b, and 0 if
39 * a == b
40 */
41 public int compare(Instant a, Instant b, boolean forceSecondsOnly) {
42 long aSeconds = a.getEpochSecond();
43 long bSeconds = b.getEpochSecond();
44 int result = Long.compare(aSeconds, bSeconds);
45 if (result != 0) {
46 return result;
47 }
48 int aSubSecond = a.getNano();
49 int bSubSecond = b.getNano();
50 if (forceSecondsOnly || (aSubSecond == 0)
51 || (bSubSecond == 0)) {
52 // Don't check the subseconds part.
53 return 0;
54 } else if (aSubSecond != bSubSecond) {
55 // If either has nothing smaller than a millisecond, compare only
56 // milliseconds.
57 int aSubMillis = aSubSecond % 1_000_000;
58 int bSubMillis = bSubSecond % 1_000_000;
59 if (aSubMillis == 0) {
60 bSubSecond -= bSubMillis;
61 } else if (bSubMillis == 0) {
62 aSubSecond -= aSubMillis;
63 } else {
64 // Same again, but for microsecond resolution. NTFS has 100ns
65 // resolution, but WindowsFileAttributes may provide only
66 // microseconds (1000ns). Similar for some Unix file systems.
67 int aSubMicros = aSubSecond % 1000;
68 int bSubMicros = bSubSecond % 1000;
69 if (aSubMicros == 0) {
70 bSubSecond -= bSubMicros;
71 } else if (bSubMicros == 0) {
72 aSubSecond -= aSubMicros;
73 }
74 }
75 }
76 return Integer.compare(aSubSecond, bSubSecond);
77 }
78
79 }