Timestamps

Learn how to work effectively with timestamps in the Synnax TypeScript client.

Working with high-resolution timestamps in JavaScript is tricky. We provide several utility classes to make it easier.

JavaScript’s Limitations

Synnax stores timestamps as 64-bit integers representing the number of nanoseconds elapsed since the unix epoch in UTC. This is unlike JavaScript’s native Date object, which only supports millisecond precision.

Numbers in JavaScript are represented as 64-bit floating point numbers, which means that they can only represent integers up to 2^53 accurately. This means that you may lose precision for certain timestamps. Also, doing arithmetic with timestamps expressed as floating point numbers can lead to rounding errors.

TimeStamp

Synnax provides the TimeStamp utility class to effectively work with nanosecond timestamps in JavaScript. It wraps a bigint to store a unix timestamp in nanoseconds.

Constructing a TimeStamp

There are several easy ways to construct a TimeStamp:

import { TimeStamp } from "@synnaxlabs/client";
// From the current time
const now = TimeStamp.now(); 
// From a Date object
const ts = new TimeStamp(new Date("2021-01-01T00:00:00Z"));
// From a string
const ts = new TimeStamp("2021-01-01T00:00:00Z");
// From a number of nanoseconds
const ts = new TimeStamp(1000000000);
// From a bigint of nanoseconds
const ts = new TimeStamp(BigInt(1000000000));
// From utility functions
const ts = TimeStamp.now().sub(TimeStamp.seconds(1));

Any of these formats can be passed to common methods used throughout the Synnax client. The union of these formats is called a CrudeTimeStamp. Examples include read, write, openIterator, openStreamer, and openWriter.

Converting to a Date

You can convert a TimeStamp to a Date object using the date method:

const ts = TimeStamp.now();
const date = ts.date();

Arithmetic

You can perform arithmetic on TimeStamp objects:

const ts1 = TimeStamp.now();
const ts2 = ts1.add(TimeStamp.seconds(1));
const diff = ts2.sub(ts1);

Comparisons

You can compare TimeStamp objects:

const ts1 = TimeStamp.now();
const ts2 = ts1.add(TimeStamp.seconds(1));
const isAfter = ts2.after(ts1);
const isAfterEq = ts2.afterEq(ts1);
const isBefore = ts1.before(ts2);
const isBeforeEq = ts1.beforeEq(ts2);

Accessing the Underlying Value

You can access the underlying bigint value using the value property:

const ts = TimeStamp.now();
const value = ts.value;

TimeSpan

TimeSpan is a utility class that represents a duration of time. It wraps a bigint to store a duration in nanoseconds.

Constructing a TimeSpan

You can construct a TimeSpan directly from a number of nanoseconds, but it’s generally easier to use the utility functions:

import { TimeSpan } from "@synnaxlabs/client";

// From a number of nanoseconds
const span = new TimeSpan(1000000000);
// From a utility function
const span = TimeSpan.hours(1);
// From multiple utility functions
const span = TimeSpan.days(1).add(TimeSpan.hours(1)).add(TimeSpan.minutes(1));

Performing Arithmetic

You can perform arithmetic on TimeSpan objects:

const span1 = TimeSpan.hours(1);
const span2 = span1.add(TimeSpan.minutes(1));
const diff = span2.sub(span1);

Accessing the Underlying Value

You can access the underlying bigint value using the value property:

const span = TimeSpan.hours(1);
const value = span.value;

TimeRange

TimeRange is another utility class that represents a range of time. It consists of two TimeStamp objects called start and end.

Constructing a TimeRange

You can construct a TimeRange from two timestamps in any of the formats that TimeStamp supports:

import { TimeRange } from "@synnaxlabs/client";

const start = TimeStamp.now();
const end = start.add(TimeStamp.seconds(1));
// From TimeStamp objects
const range = new TimeRange(start, end);
// From dates
const range = new TimeRange(
    new Date("2021-01-01T00:00:00Z"), 
    new Date("2021-01-01T00:00:01Z")
);
// From strings
const range = new TimeRange("2021-01-01T00:00:00Z", "2021-01-01T00:00:01Z");
// From numbers
const range = new TimeRange(1000000000, 2000000000);
// From bigints
const range = new TimeRange(BigInt(1000000000), BigInt(2000000000));
// From a mix of formats
const range = new TimeRange(BigInt(1000000000), "2021-01-01T00:00:01Z");
// From an object
const range = TimeRange.from({
    start: TimeStamp.now(),
    end: TimeStamp.now().add(TimeStamp.seconds(1))
});

Checking if a TimeStamp Is in a TimeRange

You can check if a TimeStamp is in a TimeRange using the contains method:

const range = new TimeRange(
    new Date("2021-01-01T00:00:00Z"), 
    new Date("2021-01-01T00:00:01Z")
);
const ts = new TimeStamp("2021-01-01T00:00:00.5Z");
const isIn = range.contains(ts);
console.log(isIn); // true

Checking if Two TimeRanges Overlap

You can check if two TimeRange objects overlap using the overlaps method:

const range1 = new TimeRange(
    new Date("2021-01-01T00:00:00Z"), 
    new Date("2021-01-01T00:00:01Z")
);
const range2 = new TimeRange(
    new Date("2021-01-01T00:00:00.5Z"), 
    new Date("2021-01-01T00:00:01.5Z")
);
const doesOverlap = range1.overlapsWith(range2);
console.log(doesOverlap); // true

Getting the TimeSpan of a TimeRange

You can get the TimeSpan of a TimeRange using the span property:

const range = new TimeRange(
    new Date("2021-01-01T00:00:00Z"), 
    new Date("2021-01-01T00:00:01Z")
);
const span = range.span;
console.log(span.seconds); // 1