1 package com.atlassian.scheduler.core.util;
2
3 import static com.atlassian.util.concurrent.Assertions.isTrue;
4
5 /**
6 * Tool for quantizing millisecond time intervals to a broader resolution while
7 * guarding against sign overflows.
8 *
9 * @since v1.0
10 */
11 public class TimeIntervalQuantizer {
12 private static final int MILLIS_PER_MINUTE = 60000;
13
14 /**
15 * Quantizes millisecond time intervals to the specified resolution, rounding up.
16 * Examples:
17 * <ul>
18 * <li>{@code quantize(0,50)} → {@code 0}</li>
19 * <li>{@code quantize(123,10)} → {@code 130}</li>
20 * <li>{@code quantize(11,15000)} → {@code 15000}</li>
21 * <li>{@code quantize(127249,60000)} → {@code 180000}</li>
22 * </ul>
23 *
24 * @param intervalInMilliseconds the time interval to be quantized
25 * @param resolution the time resolution to honour, in milliseconds.
26 * @return the quantized time interval, in milliseconds with the specified resolution
27 */
28 public static long quantize(long intervalInMilliseconds, int resolution) {
29 isTrue("intervalInMilliseconds cannot be negative", intervalInMilliseconds >= 0L);
30 if (resolution <= 1) {
31 return intervalInMilliseconds;
32 }
33
34 final long remainder = intervalInMilliseconds % resolution;
35 if (remainder == 0L) {
36 return intervalInMilliseconds;
37 }
38
39 return roundUpWithBoundsCheck(intervalInMilliseconds - remainder, resolution);
40 }
41
42 private static long roundUpWithBoundsCheck(final long floor, final int resolution) {
43 if (floor >= Long.MAX_VALUE - resolution) {
44 return Long.MAX_VALUE;
45 }
46
47 return floor + resolution;
48 }
49
50 /**
51 * Quantizes millisecond time intervals to a one minute resolution, rounding up.
52 * Examples:
53 * <ul>
54 * <li>{@code quantizeToMinutes(0)} → {@code 0}</li>
55 * <li>{@code quantizeToMinutes(123)} → {@code 60000}</li>
56 * <li>{@code quantizeToMinutes(127249)} → {@code 180000}</li>
57 * </ul>
58 *
59 * @param intervalInMilliseconds the time interval to be quantized
60 * @return the quantized time interval, in milliseconds with one minute resolution
61 */
62 public static long quantizeToMinutes(long intervalInMilliseconds) {
63 return quantize(intervalInMilliseconds, MILLIS_PER_MINUTE);
64 }
65 }