Durations.java
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf.util;
32 
33 import static com.google.common.base.Preconditions.checkArgument;
34 import static com.google.common.math.IntMath.checkedAdd;
35 import static com.google.common.math.IntMath.checkedSubtract;
36 import static com.google.common.math.LongMath.checkedAdd;
37 import static com.google.common.math.LongMath.checkedMultiply;
38 import static com.google.common.math.LongMath.checkedSubtract;
39 import static com.google.protobuf.util.Timestamps.MICROS_PER_SECOND;
40 import static com.google.protobuf.util.Timestamps.MILLIS_PER_SECOND;
41 import static com.google.protobuf.util.Timestamps.NANOS_PER_MICROSECOND;
42 import static com.google.protobuf.util.Timestamps.NANOS_PER_MILLISECOND;
43 import static com.google.protobuf.util.Timestamps.NANOS_PER_SECOND;
44 
45 import com.google.errorprone.annotations.CanIgnoreReturnValue;
47 import java.text.ParseException;
48 import java.util.Comparator;
49 
54 public final class Durations {
55  static final long DURATION_SECONDS_MIN = -315576000000L;
56  static final long DURATION_SECONDS_MAX = 315576000000L;
57 
58  private static final long SECONDS_PER_MINUTE = 60L;
59  private static final long SECONDS_PER_HOUR = SECONDS_PER_MINUTE * 60;
60  private static final long SECONDS_PER_DAY = SECONDS_PER_HOUR * 24;
61 
63  public static final Duration MIN_VALUE =
64  Duration.newBuilder().setSeconds(DURATION_SECONDS_MIN).setNanos(-999999999).build();
65 
67  public static final Duration MAX_VALUE =
68  Duration.newBuilder().setSeconds(DURATION_SECONDS_MAX).setNanos(999999999).build();
69 
71  public static final Duration ZERO = Duration.newBuilder().setSeconds(0L).setNanos(0).build();
72 
73  private Durations() {}
74 
75  private static final Comparator<Duration> COMPARATOR =
76  new Comparator<Duration>() {
77  @Override
78  public int compare(Duration d1, Duration d2) {
79  checkValid(d1);
80  checkValid(d2);
81  int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds());
82  return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos());
83  }
84  };
85 
90  public static Comparator<Duration> comparator() {
91  return COMPARATOR;
92  }
93 
101  public static int compare(Duration x, Duration y) {
102  return COMPARATOR.compare(x, y);
103  }
104 
114  public static boolean isValid(Duration duration) {
115  return isValid(duration.getSeconds(), duration.getNanos());
116  }
117 
127  @SuppressWarnings("GoodTime") // this is a legacy conversion API
128  public static boolean isValid(long seconds, int nanos) {
129  if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) {
130  return false;
131  }
132  if (nanos < -999999999L || nanos >= NANOS_PER_SECOND) {
133  return false;
134  }
135  if (seconds < 0 || nanos < 0) {
136  if (seconds > 0 || nanos > 0) {
137  return false;
138  }
139  }
140  return true;
141  }
142 
144  public static boolean isNegative(Duration duration) {
145  checkValid(duration);
146  return (duration.getSeconds() == 0) ? duration.getNanos() < 0 : duration.getSeconds() < 0;
147  }
148 
155  @CanIgnoreReturnValue
156  public static Duration checkNotNegative(Duration duration) {
157  checkValid(duration);
158  checkArgument(!isNegative(duration), "duration (%s) must not be negative", toString(duration));
159  return duration;
160  }
161 
168  @CanIgnoreReturnValue
169  public static Duration checkPositive(Duration duration) {
170  checkValid(duration);
171  checkArgument(
172  !isNegative(duration) && !duration.equals(ZERO),
173  "duration (%s) must be positive",
174  toString(duration));
175  return duration;
176  }
177 
179  @CanIgnoreReturnValue
180  public static Duration checkValid(Duration duration) {
181  long seconds = duration.getSeconds();
182  int nanos = duration.getNanos();
183  if (!isValid(seconds, nanos)) {
184  throw new IllegalArgumentException(
185  String.format(
186  "Duration is not valid. See proto definition for valid values. "
187  + "Seconds (%s) must be in range [-315,576,000,000, +315,576,000,000]. "
188  + "Nanos (%s) must be in range [-999,999,999, +999,999,999]. "
189  + "Nanos must have the same sign as seconds",
190  seconds, nanos));
191  }
192  return duration;
193  }
194 
201  public static Duration checkValid(Duration.Builder durationBuilder) {
202  return checkValid(durationBuilder.build());
203  }
204 
214  public static String toString(Duration duration) {
215  checkValid(duration);
216 
217  long seconds = duration.getSeconds();
218  int nanos = duration.getNanos();
219 
220  StringBuilder result = new StringBuilder();
221  if (seconds < 0 || nanos < 0) {
222  result.append("-");
223  seconds = -seconds;
224  nanos = -nanos;
225  }
226  result.append(seconds);
227  if (nanos != 0) {
228  result.append(".");
229  result.append(Timestamps.formatNanos(nanos));
230  }
231  result.append("s");
232  return result.toString();
233  }
234 
241  public static Duration parse(String value) throws ParseException {
242  // Must ended with "s".
243  if (value.isEmpty() || value.charAt(value.length() - 1) != 's') {
244  throw new ParseException("Invalid duration string: " + value, 0);
245  }
246  boolean negative = false;
247  if (value.charAt(0) == '-') {
248  negative = true;
249  value = value.substring(1);
250  }
251  String secondValue = value.substring(0, value.length() - 1);
252  String nanoValue = "";
253  int pointPosition = secondValue.indexOf('.');
254  if (pointPosition != -1) {
255  nanoValue = secondValue.substring(pointPosition + 1);
256  secondValue = secondValue.substring(0, pointPosition);
257  }
258  long seconds = Long.parseLong(secondValue);
259  int nanos = nanoValue.isEmpty() ? 0 : Timestamps.parseNanos(nanoValue);
260  if (seconds < 0) {
261  throw new ParseException("Invalid duration string: " + value, 0);
262  }
263  if (negative) {
264  seconds = -seconds;
265  nanos = -nanos;
266  }
267  try {
268  return normalizedDuration(seconds, nanos);
269  } catch (IllegalArgumentException e) {
270  throw new ParseException("Duration value is out of range.", 0);
271  }
272  }
273 
274  // Static factories
275 
277  @SuppressWarnings("GoodTime") // this is a legacy conversion API
278  public static Duration fromDays(long days) {
279  return Duration.newBuilder()
280  .setSeconds(checkedMultiply(days, SECONDS_PER_DAY))
281  .setNanos(0)
282  .build();
283  }
284 
286  @SuppressWarnings("GoodTime") // this is a legacy conversion API
287  public static Duration fromHours(long hours) {
288  return Duration.newBuilder()
289  .setSeconds(checkedMultiply(hours, SECONDS_PER_HOUR))
290  .setNanos(0)
291  .build();
292  }
293 
295  @SuppressWarnings("GoodTime") // this is a legacy conversion API
296  public static Duration fromMinutes(long minutes) {
297  return Duration.newBuilder()
298  .setSeconds(checkedMultiply(minutes, SECONDS_PER_MINUTE))
299  .setNanos(0)
300  .build();
301  }
302 
304  @SuppressWarnings("GoodTime") // this is a legacy conversion API
305  public static Duration fromSeconds(long seconds) {
306  return normalizedDuration(seconds, 0);
307  }
308 
310  @SuppressWarnings("GoodTime") // this is a legacy conversion API
311  public static Duration fromMillis(long milliseconds) {
312  return normalizedDuration(
313  milliseconds / MILLIS_PER_SECOND,
314  (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
315  }
316 
318  @SuppressWarnings("GoodTime") // this is a legacy conversion API
319  public static Duration fromMicros(long microseconds) {
320  return normalizedDuration(
321  microseconds / MICROS_PER_SECOND,
322  (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
323  }
324 
326  @SuppressWarnings("GoodTime") // this is a legacy conversion API
327  public static Duration fromNanos(long nanoseconds) {
328  return normalizedDuration(
329  nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND));
330  }
331 
332  // Conversion APIs
333 
338  @SuppressWarnings("GoodTime") // this is a legacy conversion API
339  public static long toDays(Duration duration) {
340  return checkValid(duration).getSeconds() / SECONDS_PER_DAY;
341  }
342 
347  @SuppressWarnings("GoodTime") // this is a legacy conversion API
348  public static long toHours(Duration duration) {
349  return checkValid(duration).getSeconds() / SECONDS_PER_HOUR;
350  }
351 
356  @SuppressWarnings("GoodTime") // this is a legacy conversion API
357  public static long toMinutes(Duration duration) {
358  return checkValid(duration).getSeconds() / SECONDS_PER_MINUTE;
359  }
360 
365  @SuppressWarnings("GoodTime") // this is a legacy conversion API
366  public static long toSeconds(Duration duration) {
367  return checkValid(duration).getSeconds();
368  }
369 
379  @SuppressWarnings({
380  "DurationSecondsToDouble", // that's the whole point of this method
381  "GoodTime" // this is a legacy conversion API
382  })
383  public static double toSecondsAsDouble(Duration duration) {
384  checkValid(duration);
385  return duration.getSeconds() + duration.getNanos() / 1e9;
386  }
387 
392  @SuppressWarnings("GoodTime") // this is a legacy conversion API
393  public static long toMillis(Duration duration) {
394  checkValid(duration);
395  return checkedAdd(
396  checkedMultiply(duration.getSeconds(), MILLIS_PER_SECOND),
397  duration.getNanos() / NANOS_PER_MILLISECOND);
398  }
399 
404  @SuppressWarnings("GoodTime") // this is a legacy conversion API
405  public static long toMicros(Duration duration) {
406  checkValid(duration);
407  return checkedAdd(
408  checkedMultiply(duration.getSeconds(), MICROS_PER_SECOND),
409  duration.getNanos() / NANOS_PER_MICROSECOND);
410  }
411 
413  @SuppressWarnings("GoodTime") // this is a legacy conversion API
414  public static long toNanos(Duration duration) {
415  checkValid(duration);
416  return checkedAdd(
417  checkedMultiply(duration.getSeconds(), NANOS_PER_SECOND), duration.getNanos());
418  }
419 
420  // Math operations
421 
423  public static Duration add(Duration d1, Duration d2) {
424  checkValid(d1);
425  checkValid(d2);
426  return normalizedDuration(
427  checkedAdd(d1.getSeconds(), d2.getSeconds()), checkedAdd(d1.getNanos(), d2.getNanos()));
428  }
429 
431  public static Duration subtract(Duration d1, Duration d2) {
432  checkValid(d1);
433  checkValid(d2);
434  return normalizedDuration(
435  checkedSubtract(d1.getSeconds(), d2.getSeconds()),
436  checkedSubtract(d1.getNanos(), d2.getNanos()));
437  }
438 
439  static Duration normalizedDuration(long seconds, int nanos) {
440  if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
441  seconds = checkedAdd(seconds, nanos / NANOS_PER_SECOND);
442  nanos %= NANOS_PER_SECOND;
443  }
444  if (seconds > 0 && nanos < 0) {
445  nanos += NANOS_PER_SECOND; // no overflow since nanos is negative (and we're adding)
446  seconds--; // no overflow since seconds is positive (and we're decrementing)
447  }
448  if (seconds < 0 && nanos > 0) {
449  nanos -= NANOS_PER_SECOND; // no overflow since nanos is positive (and we're subtracting)
450  seconds++; // no overflow since seconds is negative (and we're incrementing)
451  }
452  Duration duration = Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build();
453  return checkValid(duration);
454  }
455 }
com.google.protobuf.util.Durations.subtract
static Duration subtract(Duration d1, Duration d2)
Definition: Durations.java:431
com.google.protobuf.util.Durations.toMinutes
static long toMinutes(Duration duration)
Definition: Durations.java:357
com.google.protobuf.util.Durations.COMPARATOR
static final Comparator< Duration > COMPARATOR
Definition: Durations.java:75
com.google.protobuf.util.Durations.toSeconds
static long toSeconds(Duration duration)
Definition: Durations.java:366
com.google.protobuf.util.Durations.parse
static Duration parse(String value)
Definition: Durations.java:241
com.google.protobuf
Definition: ProtoCaliperBenchmark.java:2
y
GLint y
Definition: glcorearb.h:2768
com.google.protobuf.util.Durations.toHours
static long toHours(Duration duration)
Definition: Durations.java:348
com.google.protobuf.util.Durations.toString
static String toString(Duration duration)
Definition: Durations.java:214
com.google.protobuf.util.Durations.comparator
static Comparator< Duration > comparator()
Definition: Durations.java:90
x
GLint GLenum GLint x
Definition: glcorearb.h:2834
com.google.protobuf.util.Durations.isNegative
static boolean isNegative(Duration duration)
Definition: Durations.java:144
com.google.protobuf.util.Durations.checkNotNegative
static Duration checkNotNegative(Duration duration)
Definition: Durations.java:156
com.google.protobuf.util.Durations.isValid
static boolean isValid(Duration duration)
Definition: Durations.java:114
com.google.protobuf.util.Durations.MIN_VALUE
static final Duration MIN_VALUE
Definition: Durations.java:63
com.google.protobuf.util.Durations
Definition: Durations.java:54
com.google.protobuf.util.Durations.fromNanos
static Duration fromNanos(long nanoseconds)
Definition: Durations.java:327
com.google.protobuf.util.Durations.SECONDS_PER_MINUTE
static final long SECONDS_PER_MINUTE
Definition: Durations.java:58
com.google.protobuf.util.Durations.toMillis
static long toMillis(Duration duration)
Definition: Durations.java:393
com.google.protobuf.util
Definition: Durations.java:31
com.google.protobuf.util.Durations.fromDays
static Duration fromDays(long days)
Definition: Durations.java:278
com.google.protobuf.util.Durations.Durations
Durations()
Definition: Durations.java:73
com.google.protobuf.util.Durations.fromHours
static Duration fromHours(long hours)
Definition: Durations.java:287
com.google.protobuf.util.Durations.add
static Duration add(Duration d1, Duration d2)
Definition: Durations.java:423
com.google.protobuf.util.Durations.SECONDS_PER_HOUR
static final long SECONDS_PER_HOUR
Definition: Durations.java:59
com.google.protobuf.util.Durations.toMicros
static long toMicros(Duration duration)
Definition: Durations.java:405
com.google.protobuf.util.Durations.SECONDS_PER_DAY
static final long SECONDS_PER_DAY
Definition: Durations.java:60
com.google.protobuf.util.Durations.checkValid
static Duration checkValid(Duration duration)
Definition: Durations.java:180
com.google.protobuf.util.Durations.compare
static int compare(Duration x, Duration y)
Definition: Durations.java:101
java
com.google.protobuf.util.Durations.ZERO
static final Duration ZERO
Definition: Durations.java:71
com.google.protobuf.util.Durations.toDays
static long toDays(Duration duration)
Definition: Durations.java:339
com.google.protobuf::Duration
Duration
struct Duration Duration
Definition: php/ext/google/protobuf/protobuf.h:631
com.google.protobuf.util.Durations.checkValid
static Duration checkValid(Duration.Builder durationBuilder)
Definition: Durations.java:201
com.google.protobuf.util.Durations.fromMinutes
static Duration fromMinutes(long minutes)
Definition: Durations.java:296
com.google.protobuf.util.Timestamps
Definition: Timestamps.java:54
com.google.protobuf.util.Durations.MAX_VALUE
static final Duration MAX_VALUE
Definition: Durations.java:67
com.google
com
com.google.protobuf.util.Durations.fromSeconds
static Duration fromSeconds(long seconds)
Definition: Durations.java:305
com.google.protobuf.util.Durations.checkPositive
static Duration checkPositive(Duration duration)
Definition: Durations.java:169
com.google.protobuf.util.Durations.fromMillis
static Duration fromMillis(long milliseconds)
Definition: Durations.java:311
Duration
Definition: duration.pb.h:69
value
GLsizei const GLfloat * value
Definition: glcorearb.h:3093
com.google.protobuf.util.Durations.toSecondsAsDouble
static double toSecondsAsDouble(Duration duration)
Definition: Durations.java:383
com.google.protobuf.util.Durations.toNanos
static long toNanos(Duration duration)
Definition: Durations.java:414
com.google.protobuf.util.Durations.fromMicros
static Duration fromMicros(long microseconds)
Definition: Durations.java:319


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:50