/** * Updates {@linkplain CommandContext.Schedule command schedule}. * * @param command a command to update * @param delay a {@linkplain CommandContext.Schedule#getDelay() delay} to set * @param schedulingTime the time when the command was scheduled by the {@code CommandScheduler} * @return an updated command */ static Command setSchedule(Command command, Duration delay, Timestamp schedulingTime) { checkNotNull(command); checkNotNull(delay); checkNotNull(schedulingTime); checkValid(schedulingTime); final CommandContext context = command.getContext(); final CommandContext.Schedule scheduleUpdated = context.getSchedule() .toBuilder() .setDelay(delay) .build(); final CommandContext contextUpdated = context.toBuilder() .setSchedule(scheduleUpdated) .build(); final Command.SystemProperties sysProps = command.getSystemProperties() .toBuilder() .setSchedulingTime(schedulingTime) .build(); final Command result = command.toBuilder() .setContext(contextUpdated) .setSystemProperties(sysProps) .build(); return result; }
private static long getDelayMilliseconds(Command command) { final Schedule schedule = command.getContext().getSchedule(); final Duration delay = schedule.getDelay(); final long delaySec = delay.getSeconds(); final long delayMillisFraction = delay.getNanos() / NANOS_IN_MILLISECOND; /** * Maximum value of {@link Duration#getSeconds()} is * <a href="https://github.com/google/protobuf/blob/master/src/google/protobuf/duration.proto"+315,576,000,000.</a>. * * {@link Long.MAX_VALUE} is +9,223,372,036,854,775,807. That's why it is safe to multiply * {@code delaySec * MILLIS_IN_SECOND}. */ final long absoluteMillis = delaySec * MILLIS_IN_SECOND + delayMillisFraction; return absoluteMillis; }
/** * Returns several records sorted by timestamp ascending. * * @param timestamp1 the timestamp of first record. */ public static List<AggregateEventRecord> sequenceFor(ProjectId id, Timestamp timestamp1) { final Duration delta = seconds(10); final Timestamp timestamp2 = add(timestamp1, delta); final Timestamp timestamp3 = add(timestamp2, delta); final TestEventFactory eventFactory = newInstance(Given.class); final Event e1 = eventFactory.createEvent(projectCreated(id, projectName(id)), null, timestamp1); final AggregateEventRecord record1 = StorageRecord.create(timestamp1, e1); final Event e2 = eventFactory.createEvent(taskAdded(id), null, timestamp2); final AggregateEventRecord record2 = StorageRecord.create(timestamp2, e2); final Event e3 = eventFactory.createEvent(EventMessage.projectStarted(id), null, timestamp3); final AggregateEventRecord record3 = StorageRecord.create(timestamp3, e3); return newArrayList(record1, record2, record3); }
@Test public void reschedule_commands_from_storage() { final Timestamp schedulingTime = minutesAgo(3); final Duration delayPrimary = Durations2.fromMinutes(5); final Duration newDelayExpected = Durations2.fromMinutes(2); // = 5 - 3 final List<Command> commandsPrimary = newArrayList(createProject(), addTask(), startProject()); storeAsScheduled(commandsPrimary, delayPrimary, schedulingTime); commandBus.rescheduleCommands(); final ArgumentCaptor<Command> commandCaptor = ArgumentCaptor.forClass(Command.class); verify(scheduler, times(commandsPrimary.size())).schedule(commandCaptor.capture()); final List<Command> commandsRescheduled = commandCaptor.getAllValues(); for (Command cmd : commandsRescheduled) { final long actualDelay = getDelaySeconds(cmd); Tests.assertSecondsEqual(newDelayExpected.getSeconds(), actualDelay, /*maxDiffSec=*/1); } }
@Test public void set_expired_scheduled_command_status_to_error_if_time_to_post_them_passed() { final List<Command> commands = newArrayList(createProject(), addTask(), startProject()); final Duration delay = fromMinutes(5); final Timestamp schedulingTime = TimeTests.Past.minutesAgo(10); // time to post passed storeAsScheduled(commands, delay, schedulingTime); commandBus.rescheduleCommands(); for (Command cmd : commands) { final CommandEnvelope envelope = CommandEnvelope.of(cmd); final Message msg = envelope.getMessage(); final CommandId id = envelope.getId(); // Check the expired status error was set. final ProcessingStatus status = getProcessingStatus(envelope); // Check that the logging was called. verify(log).errorExpiredCommand(msg, id); final Error expected = CommandExpiredException.commandExpired(cmd); assertEquals(expected, status.getError()); } }
/** * Convert Duration to string format. The string format will contains 3, 6, or 9 fractional digits * depending on the precision required to represent the exact Duration value. For example: "1s", * "1.010s", "1.000000100s", "-3.100s" The range that can be represented by Duration is from * -315,576,000,000 to +315,576,000,000 inclusive (in seconds). * * @return The string representation of the given duration. * @throws IllegalArgumentException if the given duration is not in the valid range. */ public static String toString(Duration duration) { checkValid(duration); long seconds = duration.getSeconds(); int nanos = duration.getNanos(); StringBuilder result = new StringBuilder(); if (seconds < 0 || nanos < 0) { result.append("-"); seconds = -seconds; nanos = -nanos; } result.append(seconds); if (nanos != 0) { result.append("."); result.append(Timestamps.formatNanos(nanos)); } result.append("s"); return result.toString(); }
static Duration normalizedDuration(long seconds, int nanos) { if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) { seconds = checkedAdd(seconds, nanos / NANOS_PER_SECOND); nanos %= NANOS_PER_SECOND; } if (seconds > 0 && nanos < 0) { nanos += NANOS_PER_SECOND; // no overflow since nanos is negative (and we're adding) seconds--; // no overflow since seconds is positive (and we're decrementing) } if (seconds < 0 && nanos > 0) { nanos -= NANOS_PER_SECOND; // no overflow since nanos is positive (and we're subtracting) seconds++; // no overflow since seconds is negative (and we're incrementing) } Duration duration = Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build(); return checkValid(duration); }
private static Duration normalizedDuration(long seconds, int nanos) { if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) { seconds += nanos / NANOS_PER_SECOND; nanos %= NANOS_PER_SECOND; } if (seconds > 0 && nanos < 0) { nanos += NANOS_PER_SECOND; seconds -= 1; } if (seconds < 0 && nanos > 0) { nanos -= NANOS_PER_SECOND; seconds += 1; } if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) { throw new IllegalArgumentException("Duration is out of valid range."); } return Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build(); }
public void testDurationConversion() throws Exception { Duration duration = TimeUtil.parseDuration("1.111111111s"); assertEquals(1111111111, TimeUtil.toNanos(duration)); assertEquals(1111111, TimeUtil.toMicros(duration)); assertEquals(1111, TimeUtil.toMillis(duration)); duration = TimeUtil.createDurationFromNanos(1111111111); assertEquals("1.111111111s", TimeUtil.toString(duration)); duration = TimeUtil.createDurationFromMicros(1111111); assertEquals("1.111111s", TimeUtil.toString(duration)); duration = TimeUtil.createDurationFromMillis(1111); assertEquals("1.111s", TimeUtil.toString(duration)); duration = TimeUtil.parseDuration("-1.111111111s"); assertEquals(-1111111111, TimeUtil.toNanos(duration)); assertEquals(-1111111, TimeUtil.toMicros(duration)); assertEquals(-1111, TimeUtil.toMillis(duration)); duration = TimeUtil.createDurationFromNanos(-1111111111); assertEquals("-1.111111111s", TimeUtil.toString(duration)); duration = TimeUtil.createDurationFromMicros(-1111111); assertEquals("-1.111111s", TimeUtil.toString(duration)); duration = TimeUtil.createDurationFromMillis(-1111); assertEquals("-1.111s", TimeUtil.toString(duration)); }
@Override public void doMerge(JsonParser parser, int unused, Message.Builder messageBuilder) throws IOException { Duration.Builder builder = (Duration.Builder) messageBuilder; try { builder.mergeFrom(Durations.parse(ParseSupport.parseString(parser))); } catch (ParseException e) { throw new InvalidProtocolBufferException( "Failed to readValue duration: " + parser.getText()); } }
private void mergeDuration(JsonElement json, Message.Builder builder) throws InvalidProtocolBufferException { try { Duration value = Durations.parse(json.getAsString()); builder.mergeFrom(value.toByteString()); } catch (ParseException e) { throw new InvalidProtocolBufferException("Failed to parse duration: " + json); } }
public Watchdog(Duration petTimeout, Runnable runnable) { this.runnable = runnable; this.petTimeout = petTimeout; stopped = false; done = false; pet(); }
@Before public void setUp() throws Exception { String uniqueServerName = "in-process server for " + getClass(); memoryInstanceConfig = MemoryInstanceConfig.newBuilder() .setListOperationsDefaultPageSize(1024) .setListOperationsMaxPageSize(16384) .setTreeDefaultPageSize(1024) .setTreeMaxPageSize(16384) .setOperationPollTimeout(Duration.newBuilder() .setSeconds(10) .setNanos(0)) .setOperationCompletedDelay(Duration.newBuilder() .setSeconds(10) .setNanos(0)) .build(); BuildFarmServerConfig.Builder configBuilder = BuildFarmServerConfig.newBuilder().setPort(0); configBuilder.addInstancesBuilder() .setName("memory") .setMemoryInstanceConfig(memoryInstanceConfig); server = new BuildFarmServer( InProcessServerBuilder.forName(uniqueServerName).directExecutor(), configBuilder.build()); server.start(); inProcessChannel = InProcessChannelBuilder.forName(uniqueServerName) .directExecutor().build(); }
@Override public Duration convert(String value) { try { if (value.isEmpty()) { return Durations.fromMillis(0); } long millis = 0; boolean negative = value.startsWith("-"); int index = negative ? 1 : 0; Pattern unitPattern = Pattern.compile( "(?x) (?<whole>[0-9]+)? (?<frac>\\.[0-9]*)? (?<unit>d|h|ms?|s)", Pattern.CASE_INSENSITIVE); Matcher matcher = unitPattern.matcher(value); while (matcher.find(index) && matcher.start() == index) { Preconditions.checkArgument(CharMatcher.inRange('0', '9').matchesAnyOf(matcher.group(0))); long whole = Long.parseLong(MoreObjects.firstNonNull(matcher.group("whole"), "0")); double frac = Double.parseDouble("0" + MoreObjects.firstNonNull(matcher.group("frac"), "")); int millisPerUnit = millisPerUnit(matcher.group("unit")); millis += millisPerUnit * whole; millis += (long) (millisPerUnit * frac); index = matcher.end(); } if (index < value.length()) { throw new IllegalArgumentException("Could not parse entire duration"); } if (negative) { millis = -millis; } return Durations.fromMillis(millis); } catch (Exception e) { throw new ParameterException( getErrorString(value, "A duration string must include units (d|h|m|s|ms).")); } }
@Test public void testDurationIsNotProto2() { // Duration is a core Protocol Buffers type that uses proto3 syntax. thrown.expect(IllegalArgumentException.class); thrown.expectMessage(Duration.class.getCanonicalName()); thrown.expectMessage("in file " + Duration.getDescriptor().getFile().getName()); checkProto2Syntax(Duration.class, ExtensionRegistry.getEmptyRegistry()); }
@Test public void pass_null_tolerance_test() { new NullPointerTester() .setDefault(FileDescriptor.class, DEFAULT_FILE_DESCRIPTOR) .setDefault(Timestamp.class, getCurrentTime()) .setDefault(Duration.class, Durations2.ZERO) .setDefault(Command.class, requestFactory.createCommand(StringValue.getDefaultInstance(), minutesAgo(1))) .setDefault(CommandContext.class, requestFactory.createCommandContext()) .setDefault(ZoneOffset.class, ZoneOffsets.UTC) .setDefault(UserId.class, GivenUserId.newUuid()) .testStaticMethods(Commands.class, NullPointerTester.Visibility.PACKAGE); }
/** * Sets a new scheduling time in the {@linkplain CommandContext.Schedule context} * of the passed command. * * @param command a command to update * @param schedulingTime the time when the command was scheduled by the {@code CommandScheduler} * @return an updated command */ static Command setSchedulingTime(Command command, Timestamp schedulingTime) { checkNotNull(command); checkNotNull(schedulingTime); final Duration delay = command.getContext() .getSchedule() .getDelay(); final Command result = setSchedule(command, delay, schedulingTime); return result; }
private void reschedule(Command command) { final Timestamp now = getCurrentTime(); final Timestamp timeToPost = getTimeToPost(command); if (isLaterThan(now, /*than*/ timeToPost)) { onScheduledCommandExpired(command); } else { final Interval interval = Intervals.between(now, timeToPost); final Duration newDelay = Intervals.toDuration(interval); final Command updatedCommand = CommandScheduler.setSchedule(command, newDelay, now); scheduler().schedule(updatedCommand); } }
@Test public void write_records_and_load_history_till_last_snapshot() { final Duration delta = seconds(10); final Timestamp time1 = getCurrentTime(); final Timestamp time2 = add(time1, delta); final Timestamp time3 = add(time2, delta); storage.writeRecord(id, StorageRecord.create(time1)); storage.writeSnapshot(id, newSnapshot(time2)); testWriteRecordsAndLoadHistory(time3); }
@Test public void update_schedule_options() { final Command cmd = requestFactory.command() .create(toMessage(newUuid())); final Timestamp schedulingTime = getCurrentTime(); final Duration delay = Durations2.minutes(5); final Command cmdUpdated = setSchedule(cmd, delay, schedulingTime); final CommandContext.Schedule schedule = cmdUpdated.getContext() .getSchedule(); assertEquals(delay, schedule.getDelay()); assertEquals(schedulingTime, cmdUpdated.getSystemProperties() .getSchedulingTime()); }
static Command createProject(Duration delay) { final CmdCreateProject projectMessage = CommandMessage.createProjectMessage(); final CommandContext commandContext = GivenCommandContext.withScheduledDelayOf(delay); final CommandFactory commandFactory = TestActorRequestFactory.newInstance(ACommand.class) .command(); final Command cmd = commandFactory.createBasedOnContext(projectMessage, commandContext); return cmd; }
void storeAsScheduled(Iterable<Command> commands, Duration delay, Timestamp schedulingTime) { for (Command cmd : commands) { final Command cmdWithSchedule = setSchedule(cmd, delay, schedulingTime); commandStore.store(cmdWithSchedule, SCHEDULED); } }
@Test public void read_events_by_time_bounds() { final Duration delta = Durations2.seconds(111); final Timestamp present = getCurrentTime(); final Timestamp past = subtract(present, delta); final Timestamp future = add(present, delta); final Event eventInPast = projectCreated(past); final Event eventInPresent = projectCreated(present); final Event eventInFuture = projectCreated(future); eventStore.append(eventInPast); eventStore.append(eventInPresent); eventStore.append(eventInFuture); final EventStreamQuery query = EventStreamQuery.newBuilder() .setAfter(past) .setBefore(future) .build(); final AtomicBoolean done = new AtomicBoolean(false); final Collection<Event> resultEvents = newConcurrentHashSet(); eventStore.read(query, new ResponseObserver(resultEvents, done)); assertDone(done); assertSize(1, resultEvents); final Event event = resultEvents.iterator() .next(); assertEquals(eventInPresent, event); }
@Test public void read_events_by_time_and_type() { final Duration delta = Durations2.seconds(111); final Timestamp present = getCurrentTime(); final Timestamp past = subtract(present, delta); final Timestamp future = add(present, delta); final Event eventInPast = taskAdded(past); final Event eventInPresent = projectCreated(present); final Event eventInFuture = taskAdded(future); eventStore.append(eventInPast); eventStore.append(eventInPresent); eventStore.append(eventInFuture); final EventFilter taskAddedType = EventFilter.newBuilder() .setEventType(of(TaskAdded.class).value()) .build(); final EventStreamQuery query = EventStreamQuery.newBuilder() .setAfter(past) .addFilter(taskAddedType) .build(); final AtomicBoolean done = new AtomicBoolean(false); final Collection<Event> resultEvents = newConcurrentHashSet(); eventStore.read(query, new ResponseObserver(resultEvents, done)); assertDone(done); assertSize(1, resultEvents); final Event event = resultEvents.iterator() .next(); assertEquals(eventInFuture, event); }
@Test public void compare_timestamps_by_GT() { final Duration delta = seconds(5); final Timestamp small = getCurrentTime(); final Timestamp medium = add(small, delta); final Timestamp big = add(medium, delta); assertTrue(eval(medium, GREATER_THAN, small)); assertTrue(eval(big, GREATER_THAN, medium)); assertTrue(eval(big, GREATER_THAN, small)); assertFalse(eval(small, GREATER_THAN, small)); assertFalse(eval(small, GREATER_THAN, big)); assertFalse(eval(nullRef(), GREATER_THAN, small)); }
@Test public void compare_timestamps_by_GE() { final Duration delta = seconds(5); final Timestamp small = getCurrentTime(); final Timestamp medium = add(small, delta); final Timestamp big = add(medium, delta); assertTrue(eval(medium, GREATER_OR_EQUAL, small)); assertTrue(eval(big, GREATER_OR_EQUAL, medium)); assertTrue(eval(big, GREATER_OR_EQUAL, small)); assertTrue(eval(small, GREATER_OR_EQUAL, small)); assertFalse(eval(small, GREATER_OR_EQUAL, big)); assertFalse(eval(nullRef(), GREATER_OR_EQUAL, small)); }
@Test public void compare_timestamps_by_LT() { final Duration delta = seconds(5); final Timestamp small = getCurrentTime(); final Timestamp medium = add(small, delta); final Timestamp big = add(medium, delta); assertTrue(eval(medium, LESS_THAN, big)); assertTrue(eval(small, LESS_THAN, medium)); assertTrue(eval(small, LESS_THAN, big)); assertFalse(eval(big, LESS_THAN, big)); assertFalse(eval(big, LESS_THAN, small)); assertFalse(eval(nullRef(), LESS_THAN, nullRef())); }
@Test public void compare_timestamps_by_LE() { final Duration delta = seconds(5); final Timestamp small = getCurrentTime(); final Timestamp medium = add(small, delta); final Timestamp big = add(medium, delta); assertTrue(eval(medium, LESS_OR_EQUAL, big)); assertTrue(eval(small, LESS_OR_EQUAL, medium)); assertTrue(eval(small, LESS_OR_EQUAL, big)); assertTrue(eval(medium, LESS_OR_EQUAL, medium)); assertFalse(eval(big, LESS_OR_EQUAL, small)); assertFalse(eval(medium, LESS_OR_EQUAL, nullRef())); }
@Test public void create_with_scheduled_delay() { final Duration delay = Durations2.fromHours(42); final Schedule expectedSchedule = Schedule.newBuilder() .setDelay(delay) .build(); final CommandContext context = GivenCommandContext.withScheduledDelayOf(delay); checkValid(context); final Schedule actualSchedule = context.getSchedule(); assertEquals(expectedSchedule, actualSchedule); }
/** * Checks if the command is scheduled to be delivered later. * * @param command a command to check * @return {@code true} if the command context has a scheduling option set, * {@code false} otherwise */ public static boolean isScheduled(Command command) { checkNotNull(command); final Schedule schedule = command.getContext() .getSchedule(); final Duration delay = schedule.getDelay(); if (isNotDefault(delay)) { checkArgument(delay.getSeconds() > 0, "Command delay seconds must be a positive value."); return true; } return false; }
/** * Demonstrates listing time series and aggregating them. */ void listTimeSeriesAggregrate() throws IOException { // [START monitoring_read_timeseries_align] MetricServiceClient metricServiceClient = MetricServiceClient.create(); String projectId = System.getProperty("projectId"); ProjectName name = ProjectName.create(projectId); // Restrict time to last 20 minutes long startMillis = System.currentTimeMillis() - ((60 * 20) * 1000); TimeInterval interval = TimeInterval.newBuilder() .setStartTime(Timestamps.fromMillis(startMillis)) .setEndTime(Timestamps.fromMillis(System.currentTimeMillis())) .build(); Aggregation aggregation = Aggregation.newBuilder() .setAlignmentPeriod(Duration.newBuilder().setSeconds(600).build()) .setPerSeriesAligner(Aggregation.Aligner.ALIGN_MEAN) .build(); ListTimeSeriesRequest.Builder requestBuilder = ListTimeSeriesRequest.newBuilder() .setNameWithProjectName(name) .setFilter("metric.type=\"compute.googleapis.com/instance/cpu/utilization\"") .setInterval(interval) .setAggregation(aggregation); ListTimeSeriesRequest request = requestBuilder.build(); PagedResponseWrappers.ListTimeSeriesPagedResponse response = metricServiceClient .listTimeSeries(request); System.out.println("Got timeseries: "); for (TimeSeries ts : response.iterateAll()) { System.out.println(ts); } // [END monitoring_read_timeseries_align] }
/** * Demonstrates listing time series and aggregating and reducing them. */ void listTimeSeriesReduce() throws IOException { // [START monitoring_read_timeseries_reduce] MetricServiceClient metricServiceClient = MetricServiceClient.create(); String projectId = System.getProperty("projectId"); ProjectName name = ProjectName.create(projectId); // Restrict time to last 20 minutes long startMillis = System.currentTimeMillis() - ((60 * 20) * 1000); TimeInterval interval = TimeInterval.newBuilder() .setStartTime(Timestamps.fromMillis(startMillis)) .setEndTime(Timestamps.fromMillis(System.currentTimeMillis())) .build(); Aggregation aggregation = Aggregation.newBuilder() .setAlignmentPeriod(Duration.newBuilder().setSeconds(600).build()) .setPerSeriesAligner(Aggregation.Aligner.ALIGN_MEAN) .setCrossSeriesReducer(Aggregation.Reducer.REDUCE_MEAN) .build(); ListTimeSeriesRequest.Builder requestBuilder = ListTimeSeriesRequest.newBuilder() .setNameWithProjectName(name) .setFilter("metric.type=\"compute.googleapis.com/instance/cpu/utilization\"") .setInterval(interval) .setAggregation(aggregation); ListTimeSeriesRequest request = requestBuilder.build(); PagedResponseWrappers.ListTimeSeriesPagedResponse response = metricServiceClient .listTimeSeries(request); System.out.println("Got timeseries: "); for (TimeSeries ts : response.iterateAll()) { System.out.println(ts); } // [END monitoring_read_timeseries_reduce] }
@Override public int compare(Duration d1, Duration d2) { checkValid(d1); checkValid(d2); int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds()); return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos()); }
/** Throws an {@link IllegalArgumentException} if the given {@link Duration} is not valid. */ public static Duration checkValid(Duration duration) { long seconds = duration.getSeconds(); int nanos = duration.getNanos(); if (!isValid(seconds, nanos)) { throw new IllegalArgumentException(String.format( "Duration is not valid. See proto definition for valid values. " + "Seconds (%s) must be in range [-315,576,000,000, +315,576,000,000]. " + "Nanos (%s) must be in range [-999,999,999, +999,999,999]. " + "Nanos must have the same sign as seconds", seconds, nanos)); } return duration; }
/** * Parse from a string to produce a duration. * * @return A Duration parsed from the string. * @throws ParseException if parsing fails. */ public static Duration parse(String value) throws ParseException { // Must ended with "s". if (value.isEmpty() || value.charAt(value.length() - 1) != 's') { throw new ParseException("Invalid duration string: " + value, 0); } boolean negative = false; if (value.charAt(0) == '-') { negative = true; value = value.substring(1); } String secondValue = value.substring(0, value.length() - 1); String nanoValue = ""; int pointPosition = secondValue.indexOf('.'); if (pointPosition != -1) { nanoValue = secondValue.substring(pointPosition + 1); secondValue = secondValue.substring(0, pointPosition); } long seconds = Long.parseLong(secondValue); int nanos = nanoValue.isEmpty() ? 0 : Timestamps.parseNanos(nanoValue); if (seconds < 0) { throw new ParseException("Invalid duration string: " + value, 0); } if (negative) { seconds = -seconds; nanos = -nanos; } try { return normalizedDuration(seconds, nanos); } catch (IllegalArgumentException e) { throw new ParseException("Duration value is out of range.", 0); } }
/** * Convert a Duration to the number of milliseconds. The result will be rounded towards 0 to the * nearest millisecond. E.g., if the duration represents -1 nanosecond, it will be rounded to 0. */ public static long toMillis(Duration duration) { checkValid(duration); return checkedAdd( checkedMultiply(duration.getSeconds(), MILLIS_PER_SECOND), duration.getNanos() / NANOS_PER_MILLISECOND); }
/** * Convert a Duration to the number of microseconds. The result will be rounded towards 0 to the * nearest microseconds. E.g., if the duration represents -1 nanosecond, it will be rounded to 0. */ public static long toMicros(Duration duration) { checkValid(duration); return checkedAdd( checkedMultiply(duration.getSeconds(), MICROS_PER_SECOND), duration.getNanos() / NANOS_PER_MICROSECOND); }
/** Add two durations. */ public static Duration add(Duration d1, Duration d2) { checkValid(d1); checkValid(d2); return normalizedDuration( checkedAdd(d1.getSeconds(), d2.getSeconds()), checkedAdd(d1.getNanos(), d2.getNanos())); }