@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
426 lines • 17.7 kB
JavaScript
/**
* SPDX-License-Identifier: Apache-2.0
*/
import { IllegalArgumentError } from '../errors.js';
import { MathEx } from '../util/math_ex.js';
import { Time } from './time.js';
/**
* A time-based amount of time, such as '34.5 seconds'.
*
* This class models a quantity or amount of time in terms of seconds and nanoseconds. It can be accessed using other
* duration-based units, such as minutes and hours. In addition, the DAYS unit can be used and is treated as exactly
* equal to 24 hours, thus ignoring daylight savings effects.
*
* A physical duration could be of infinite length. The duration uses nanosecond resolution with a maximum value of the
* seconds that can be held in a long. This is greater than the current estimated age of the universe.
*
* The range of a duration requires the storage of a number larger than a long. To achieve this, the class stores a long
* representing seconds and an integer representing nanosecond-of-second, which will always be between 0 and 999,999,999.
* The model is of a directed duration, meaning that the duration may be negative.
*
* The duration is measured in "seconds", but these are not necessarily identical to the scientific "SI second"
* definition based on atomic clocks. This difference only impacts durations measured near a leap-second and should not
* affect most applications.
*
* This is a value-based class; use of identity-sensitive operations on instances of Duration may have unpredictable
* results and should be avoided. The equals method should be used for comparisons.
*/
export class Duration {
seconds;
nanos;
/**
* A constant for a duration of zero.
*/
static ZERO = new Duration(0, 0);
/**
* A constant for a duration of forever.
*/
static FOREVER = new Duration(Number.MAX_SAFE_INTEGER, 999_999_999);
/**
* Creates a new instance of Duration with the specified number of seconds and nanoseconds.
* This is a private constructor and not intended to be called directly.
*
* @param seconds - the number of seconds
* @param nanos - the number of nanoseconds
*/
constructor(seconds, nanos) {
this.seconds = seconds;
this.nanos = nanos;
Duration.checkValidNanos(nanos);
}
/**
* Checks if this duration is zero.
*
* @returns true if this duration is zero; false otherwise.
*/
isZero() {
return (this.seconds | this.nanos) === 0;
}
/**
* Checks if this duration is negative.
*
* @returns true if this duration is negative; false otherwise.
*/
isNegative() {
return this.seconds < 0;
}
/**
* Creates a new Duration instance with the specified number of seconds. The current number of nanoseconds in this
* duration is preserved.
*
* @param seconds - the number of seconds for the new duration
* @returns a new Duration instance with the specified number of seconds.
*/
withSeconds(seconds) {
return Duration.create(seconds, this.nanos);
}
/**
* Creates a new Duration instance with the specified number of nanoseconds. The current number of seconds in this
* duration is preserved.
*
* @param nanos - the number of nanoseconds for the new duration
* @returns a new Duration instance with the specified number of nanoseconds.
*/
withNanos(nanos) {
Duration.checkValidNanos(nanos);
return Duration.create(this.seconds, nanos);
}
/**
* Creates a new Duration instance by adding the specified duration to this duration.
*
* @param other - the duration to add
* @returns a new Duration instance with the sum of this duration and the specified duration.
*/
plus(other) {
return this.plusExact(other.seconds, other.nanos);
}
/**
* Creates a new Duration instance by adding the specified number of days to this duration.
*
* @param daysToAdd - the number of days to add
* @returns a new Duration instance with the sum of this duration and the specified number of days.
*/
plusDays(daysToAdd) {
return this.plusExact(MathEx.multiplyExact(daysToAdd, Time.SECONDS_PER_DAY), 0);
}
/**
* Creates a new Duration instance by adding the specified number of hours to this duration.
*
* @param hoursToAdd - the number of hours to add
* @returns a new Duration instance with the sum of this duration and the specified number of hours.
*/
plusHours(hoursToAdd) {
return this.plusExact(MathEx.multiplyExact(hoursToAdd, Time.SECONDS_PER_HOUR), 0);
}
/**
* Creates a new Duration instance by adding the specified number of minutes to this duration.
*
* @param minutesToAdd - the number of minutes to add
* @returns a new Duration instance with the sum of this duration and the specified number of minutes.
*/
plusMinutes(minutesToAdd) {
return this.plusExact(MathEx.multiplyExact(minutesToAdd, Time.SECONDS_PER_MINUTE), 0);
}
/**
* Creates a new Duration instance by adding the specified number of seconds to this duration.
*
* @param secondsToAdd - the number of seconds to add
* @returns a new Duration instance with the sum of this duration and the specified number of seconds.
*/
plusSeconds(secondsToAdd) {
return this.plusExact(secondsToAdd, 0);
}
/**
* Creates a new Duration instance by adding the specified number of milliseconds to this duration.
*
* @param millisToAdd - the number of milliseconds to add
* @returns a new Duration instance with the sum of this duration and the specified number of milliseconds.
*/
plusMillis(millisToAdd) {
return this.plusExact(Math.trunc(millisToAdd / Time.MILLIS_PER_SECOND), (millisToAdd % Time.MILLIS_PER_SECOND) * Time.NANOS_PER_MILLI);
}
/**
* Creates a new Duration instance by adding the specified number of nanoseconds to this duration.
*
* @param nanosToAdd - the number of nanoseconds to add
* @returns a new Duration instance with the sum of this duration and the specified number of nanoseconds.
*/
plusNanos(nanosToAdd) {
return this.plusExact(0, nanosToAdd);
}
/**
* Creates a new Duration instance by subtracting the specified duration from this duration.
*
* @param other - the duration to subtract
* @returns a new Duration instance with the difference of this duration and the specified duration.
*/
minus(other) {
const secondsToSubtract = other.seconds;
const nanosToSubtract = other.nanos;
if (secondsToSubtract === Number.MIN_SAFE_INTEGER) {
return this.plusExact(Number.MAX_SAFE_INTEGER, -nanosToSubtract).plusExact(1, 0);
}
return this.plusExact(-secondsToSubtract, -nanosToSubtract);
}
/**
* Creates a new Duration instance by subtracting the specified number of days from this duration.
*
* @param daysToSubtract - the number of days to subtract
* @returns a new Duration instance with the difference of this duration and the specified number of days.
*/
minusDays(daysToSubtract) {
return daysToSubtract === Number.MIN_SAFE_INTEGER
? this.plusDays(Number.MAX_SAFE_INTEGER).plusDays(1)
: this.plusDays(-daysToSubtract);
}
/**
* Creates a new Duration instance by subtracting the specified number of hours from this duration.
*
* @param hoursToSubtract - the number of hours to subtract
* @returns a new Duration instance with the difference of this duration and the specified number of hours.
*/
minusHours(hoursToSubtract) {
return hoursToSubtract === Number.MIN_SAFE_INTEGER
? this.plusHours(Number.MAX_SAFE_INTEGER).plusHours(1)
: this.plusHours(-hoursToSubtract);
}
/**
* Creates a new Duration instance by subtracting the specified number of minutes from this duration.
*
* @param minutesToSubtract - the number of minutes to subtract
* @returns a new Duration instance with the difference of this duration and the specified number of minutes.
*/
minusMinutes(minutesToSubtract) {
return minutesToSubtract === Number.MIN_SAFE_INTEGER
? this.plusMinutes(Number.MAX_SAFE_INTEGER).plusMinutes(1)
: this.plusMinutes(-minutesToSubtract);
}
/**
* Creates a new Duration instance by subtracting the specified number of seconds from this duration.
*
* @param secondsToSubtract - the number of seconds to subtract
* @returns a new Duration instance with the difference of this duration and the specified number of seconds.
*/
minusSeconds(secondsToSubtract) {
return secondsToSubtract === Number.MIN_SAFE_INTEGER
? this.plusSeconds(Number.MAX_SAFE_INTEGER).plusSeconds(1)
: this.plusSeconds(-secondsToSubtract);
}
/**
* Creates a new Duration instance by subtracting the specified number of milliseconds from this duration.
*
* @param millisToSubtract - the number of milliseconds to subtract
* @returns a new Duration instance with the difference of this duration and the specified number of milliseconds.
*/
minusMillis(millisToSubtract) {
return millisToSubtract === Number.MIN_SAFE_INTEGER
? this.plusMillis(Number.MAX_SAFE_INTEGER).plusMillis(1)
: this.plusMillis(-millisToSubtract);
}
/**
* Creates a new Duration instance by subtracting the specified number of nanoseconds from this duration.
*
* @param nanosToSubtract - the number of nanoseconds to subtract
* @returns a new Duration instance with the difference of this duration and the specified number of nanoseconds.
*/
minusNanos(nanosToSubtract) {
return nanosToSubtract === Number.MIN_SAFE_INTEGER
? this.plusNanos(Number.MAX_SAFE_INTEGER).plusNanos(1)
: this.plusNanos(-nanosToSubtract);
}
/**
* Converts this duration to days.
*
* @returns the number of days in this duration.
*/
toDays() {
return this.seconds / Time.SECONDS_PER_DAY;
}
/**
* Converts this duration to hours.
*
* @returns the number of hours in this duration.
*/
toHours() {
return this.seconds / Time.SECONDS_PER_HOUR;
}
/**
* Converts this duration to minutes.
*
* @returns the number of minutes in this duration.
*/
toMinutes() {
return this.seconds / Time.SECONDS_PER_MINUTE;
}
/**
* Converts this duration to milliseconds.
*
* @returns the number of milliseconds in this duration.
*/
toMillis() {
const millis = MathEx.multiplyExact(this.seconds, Time.MILLIS_PER_SECOND);
return MathEx.addExact(millis, Math.trunc(this.nanos / Time.NANOS_PER_MILLI));
}
/**
* Converts this duration to nanoseconds.
*
* @returns the number of nanoseconds in this duration.
*/
toNanos() {
const totalNanos = MathEx.multiplyExact(this.seconds, Time.NANOS_PER_SECOND);
return MathEx.addExact(totalNanos, this.nanos);
}
/**
* Compares this duration to the specified duration.
*
* @param other - the duration being compared to this duration
* @returns true if the two durations are equal; false otherwise.
*/
equals(other) {
return this.seconds === other.seconds && this.nanos === other.nanos;
}
/**
* Compares this duration to the specified duration.
*
* @param other - the duration being compared to this duration
* @returns a negative value if this duration is less than the specified duration, a positive value if this duration
* is greater than the specified duration, or zero if the two durations are equal.
*/
compareTo(other) {
const cmp = this.seconds - other.seconds;
if (cmp !== 0) {
return cmp;
}
return this.nanos - other.nanos;
}
/**
* Creates a new Duration instance representing the specified number of days.
*
* @param days - the number of days
* @returns a new Duration instance representing the specified number of days.
*/
static ofDays(days) {
return Duration.create(MathEx.multiplyExact(days, Time.SECONDS_PER_DAY), 0);
}
/**
* Creates a new Duration instance representing the specified number of hours.
*
* @param hours - the number of hours
* @returns a new Duration instance representing the specified number of hours.
*/
static ofHours(hours) {
return Duration.create(MathEx.multiplyExact(hours, Time.SECONDS_PER_HOUR), 0);
}
/**
* Creates a new Duration instance representing the specified number of minutes.
*
* @param minutes - the number of minutes
* @returns a new Duration instance representing the specified number of minutes.
*/
static ofMinutes(minutes) {
return Duration.create(MathEx.multiplyExact(minutes, Time.SECONDS_PER_MINUTE), 0);
}
/**
* Creates a new Duration instance representing the specified number of seconds.
*
* @param seconds - the number of seconds
* @returns a new Duration instance representing the specified number of seconds.
*/
static ofSeconds(seconds) {
return Duration.create(seconds, 0);
}
/**
* Creates a new Duration instance representing the specified number of seconds adjusted by a number of nanoseconds.
*
* @param seconds - the number of seconds
* @param nanoAdjustment - the number of nanoseconds by which to adjust the seconds
* @returns a new Duration instance representing the specified number of seconds adjusted by the specified number of nanoseconds.
*/
static ofSecondsAdjusted(seconds, nanoAdjustment) {
const secs = MathEx.addExact(seconds, MathEx.floorDiv(nanoAdjustment, Time.NANOS_PER_SECOND));
const nos = MathEx.floorMod(nanoAdjustment, Time.NANOS_PER_SECOND);
return Duration.create(secs, nos);
}
/**
* Creates a new Duration instance representing the specified number of milliseconds.
*
* @param millis - the number of milliseconds
* @returns a new Duration instance representing the specified number of milliseconds.
*/
static ofMillis(millis) {
let secs = millis / Time.MILLIS_PER_SECOND;
let mos = millis % Time.MILLIS_PER_SECOND;
if (mos < 0) {
mos += Time.MILLIS_PER_SECOND;
secs--;
}
return Duration.create(Math.trunc(secs), mos * Time.NANOS_PER_MILLI);
}
/**
* Creates a new Duration instance representing the specified number of nanoseconds.
*
* @param nanos - the number of nanoseconds
* @returns a new Duration instance representing the specified number of nanoseconds.
*/
static ofNanos(nanos) {
let secs = nanos / Time.NANOS_PER_SECOND;
let nos = nanos % Time.NANOS_PER_SECOND;
if (nos < 0) {
nos += Time.NANOS_PER_SECOND;
secs--;
}
return Duration.create(Math.trunc(secs), nos);
}
/**
* Private utility method to create a new Duration instance representing the specified number of seconds and
* nanoseconds.
*
* @param seconds - the number of seconds
* @param nanoAdjustment - the number of nanoseconds
* @returns a new Duration instance representing the specified number of seconds and nanoseconds.
*/
static create(seconds, nanoAdjustment) {
if ((seconds | nanoAdjustment) === 0) {
return Duration.ZERO;
}
return new Duration(seconds, nanoAdjustment);
}
/**
* Private utility method to create a new Duration instance by adding the specified number of seconds and nanoseconds.
*
* @param secondsToAdd - the number of seconds to add
* @param nanosToAdd - the number of nanoseconds to add
* @returns a new Duration instance with the sum of this duration and the specified number of seconds and nanoseconds.
*/
plusExact(secondsToAdd, nanosToAdd) {
if ((secondsToAdd | nanosToAdd) === 0) {
return this;
}
let epochSec = MathEx.addExact(this.seconds, secondsToAdd);
epochSec = MathEx.addExact(epochSec, Math.trunc(nanosToAdd / Time.NANOS_PER_SECOND));
nanosToAdd = nanosToAdd % Time.NANOS_PER_SECOND;
const nanoAdjustment = this.nanos + nanosToAdd;
return Duration.ofSecondsAdjusted(epochSec, nanoAdjustment);
}
/**
* Private utility method to validate the specified number of nanoseconds.
*
* @param nanos - the number of nanoseconds to validate
* @returns true if the specified number of nanoseconds is valid; false otherwise.
*/
static isValidNanos(nanos) {
return Number.isSafeInteger(nanos) && nanos >= 0 && nanos <= 999_999_999;
}
/**
* Private utility method to validate the specified number of nanoseconds.
*
* @param nanos - the number of nanoseconds to validate
* @throws IllegalArgumentError if the specified number of nanoseconds is invalid.
*/
static checkValidNanos(nanos) {
if (!Duration.isValidNanos(nanos)) {
throw new IllegalArgumentError('The nanoseconds value must be zero or greater and less than or equal to 999,999,999');
}
}
}
//# sourceMappingURL=duration.js.map