Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
feat: Enhance use of Duration
Browse files Browse the repository at this point in the history
  • Loading branch information
lightwalker-eth committed May 3, 2024
1 parent 628b509 commit 5144864
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 35 deletions.
73 changes: 72 additions & 1 deletion src/time.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, it, expect } from "vitest";

import { addSeconds, buildTimePeriod, buildTimestamp, buildTimestampMs, buildDateFromTimestamp, timestampMsToTimestamp, now, buildTimestampFromDate, buildDuration, isOverlappingTimestamp, subtractSeconds, formatTimestamp, FormatTimestampOptions, formatTimestampAsDistance, formatTimestampAsDistanceToNow } from "./time";
import { addSeconds, buildTimePeriod, buildTimestamp, buildTimestampMs, buildDateFromTimestamp, timestampMsToTimestamp, now, buildTimestampFromDate, buildDuration, isOverlappingTimestamp, subtractSeconds, formatTimestamp, FormatTimestampOptions, formatTimestampAsDistance, formatTimestampAsDistanceToNow, scaleDuration, SECONDS_PER_DAY, DAYS_PER_YEAR } from "./time";

describe("timestampMsToTimestamp() function", () => {
it("Correctly returns 0s for less than 1000ms params", () => {
Expand Down Expand Up @@ -59,6 +59,77 @@ describe("buildDuration() function", () => {
});
});

describe("scaleDuration() function", () => {

it("throws when scaled by a negative number", () => {

const seconds = 1000n;
const duration = buildDuration(seconds);
const scalar = -1;

expect(() => {scaleDuration(duration, scalar)}).toThrow();
});

it("throws when scaled by an invalid number", () => {

const seconds = 1000n;
const duration = buildDuration(seconds);
const scalar = Infinity;

expect(() => {scaleDuration(duration, scalar)}).toThrow();
});

it("scale by 0n", () => {

const seconds = 1000n;
const duration = buildDuration(seconds);
const scalar = 0n;
const result = scaleDuration(duration, scalar);

expect(result.seconds).toStrictEqual(0n);
});

it("scale by 0", () => {

const seconds = 1000n;
const duration = buildDuration(seconds);
const scalar = 0;
const result = scaleDuration(duration, scalar);

expect(result.seconds).toStrictEqual(0n);
});

it("scale by 1000n", () => {

const seconds = 1000n;
const duration = buildDuration(seconds);
const scalar = 1000n;
const result = scaleDuration(duration, scalar);

expect(result.seconds).toStrictEqual(1000000n);
});

it("scale by 1000", () => {

const seconds = 1000n;
const duration = buildDuration(seconds);
const scalar = 1000;
const result = scaleDuration(duration, scalar);

expect(result.seconds).toStrictEqual(1000000n);
});

it("scale by fractional scalar", () => {

const duration = SECONDS_PER_DAY;
const scalar = DAYS_PER_YEAR;
const result = scaleDuration(duration, scalar);

expect(result.seconds).toStrictEqual(31556952n);
});

});

describe("addSeconds() function", () => {

it("add zero duration", () => {
Expand Down
105 changes: 71 additions & 34 deletions src/time.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,89 @@
import { formatDistanceStrict } from "date-fns";
import { enUS } from 'date-fns/locale';

/**
* A Duration represents a length of time in seconds.
*/
export interface Duration {

/**
* The number of seconds in the Duration.
* Must be non-negative.
*/
seconds: bigint;
}

/**
* Builds a Duration.
*
* @param seconds - The number of seconds in the Duration.
* @returns The resulting Duration.
*/
export const buildDuration = (
seconds: bigint
): Duration => {
if (seconds < 0n)
throw new Error(`Error in buildDuration. seconds ${seconds}} is less than 0.`);

return {
seconds
};
};

/**
* Scales a Duration by the given scalar.
*
* @param duration The Duration to scale.
* @param scalar The scalar to scale the Duration by.
* @returns The scaled Duration.
* @throws If scalar is negative.
* @throws If scalar is of type number and cannot be converted to bigint.
*/
export const scaleDuration = (
duration: Duration,
scalar: bigint | number
): Duration => {

let newSeconds: bigint;

if (typeof scalar === 'number') {
try {
newSeconds = BigInt(Number(duration.seconds) * scalar);
} catch (error) {
throw new Error(`Error in scaleDuration. scalar ${scalar}} is not a valid number.`);
}
} else {
newSeconds = duration.seconds * scalar;
}

if (newSeconds < 0n) {
throw new Error(`Error in scaleDuration. scalar ${scalar}} must be a non-negative number.`);
}

return buildDuration(newSeconds);
}

export const MILLISECONDS_PER_SECOND = 1000n;
export const SECONDS_PER_MINUTE = 60n;

/**
* 60n seconds
*/
export const SECONDS_PER_MINUTE = buildDuration(60n);

/**
* 3,600n seconds
*/
export const SECONDS_PER_HOUR = 60n * SECONDS_PER_MINUTE;
export const SECONDS_PER_HOUR = scaleDuration(SECONDS_PER_MINUTE, 60n);

/**
* 86,400n seconds
*/
export const SECONDS_PER_DAY = 24n * SECONDS_PER_HOUR;
export const SECONDS_PER_DAY = scaleDuration(SECONDS_PER_HOUR, 24n);

/**
* 604,800n seconds
*/
export const SECONDS_PER_WEEK = 7n * SECONDS_PER_DAY;
export const SECONDS_PER_WEEK = scaleDuration(SECONDS_PER_DAY, 7n);

/**
* The average Gregorian calendar year is 365.2425 days in length
Expand All @@ -27,7 +93,7 @@ export const DAYS_PER_YEAR = 365.2425;
/**
* 31,556,952n seconds
*/
export const SECONDS_PER_YEAR = BigInt(Number(SECONDS_PER_DAY) * DAYS_PER_YEAR);
export const SECONDS_PER_YEAR = scaleDuration(SECONDS_PER_DAY, DAYS_PER_YEAR);

/**
* A moment in time measured in seconds.
Expand Down Expand Up @@ -169,35 +235,6 @@ export const now = (): Timestamp => {
return timestampMsToTimestamp(nowMs());
};

/**
* A Duration represents a length of time in seconds.
*/
export interface Duration {

/**
* The number of seconds in the Duration.
* Must be non-negative.
*/
seconds: bigint;
}

/**
* Builds a Duration.
*
* @param seconds - The number of seconds in the Duration.
* @returns The resulting Duration.
*/
export const buildDuration = (
seconds: bigint
): Duration => {
if (seconds < 0n)
throw new Error(`Error in buildDuration. seconds ${seconds}} is less than 0.`);

return {
seconds
};
};

/**
* Builds a new Timestamp that is incremented by the provided Duration.
*
Expand Down

0 comments on commit 5144864

Please sign in to comment.