Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve output for big numbers, require Node.js 18 #65

Merged
merged 7 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ jobs:
fail-fast: false
matrix:
node-version:
- 20
- 18
- 16
- 14
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm install
Expand Down
4 changes: 2 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export interface Options {
export type Options = {
/**
Number of digits to appear after the seconds decimal point.

Expand Down Expand Up @@ -75,7 +75,7 @@ export interface Options {
@default false
*/
readonly colonNotation?: boolean;
}
};

/**
Convert milliseconds to a human readable string: `1337000000` → `15d 11h 23m 20s`.
Expand Down
14 changes: 9 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import parseMilliseconds from 'parse-ms';

const pluralize = (word, count) => count === 1 ? word : `${word}s`;
const isZero = value => value === 0 || value === 0n;
const pluralize = (word, count) => (count === 1 || count === 1n) ? word : `${word}s`;

const SECOND_ROUNDING_EPSILON = 0.000_000_1;

Expand Down Expand Up @@ -30,7 +31,10 @@ export default function prettyMilliseconds(milliseconds, options = {}) {
};

const add = (value, long, short, valueString) => {
if ((result.length === 0 || !options.colonNotation) && value === 0 && !(options.colonNotation && short === 'm')) {
if (
(result.length === 0 || !options.colonNotation)
&& isZero(value)
&& !(options.colonNotation && short === 'm')) {
return;
}

Expand All @@ -53,7 +57,7 @@ export default function prettyMilliseconds(milliseconds, options = {}) {

const parsed = parseMilliseconds(milliseconds);

add(Math.trunc(parsed.days / 365), 'year', 'y');
add(BigInt(parsed.days) / 365n, 'year', 'y');
add(parsed.days % 365, 'day', 'd');
add(parsed.hours, 'hour', 'h');
add(parsed.minutes, 'minute', 'm');
Expand All @@ -79,13 +83,13 @@ export default function prettyMilliseconds(milliseconds, options = {}) {
? options.millisecondsDecimalDigits
: 0;

const roundedMiliseconds = millisecondsAndBelow >= 1
const roundedMilliseconds = millisecondsAndBelow >= 1
? Math.round(millisecondsAndBelow)
: Math.ceil(millisecondsAndBelow);

const millisecondsString = millisecondsDecimalDigits
? millisecondsAndBelow.toFixed(millisecondsDecimalDigits)
: roundedMiliseconds;
: roundedMilliseconds;

add(
Number.parseFloat(millisecondsString),
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"exports": "./index.js",
"types": "./index.d.ts",
"engines": {
"node": ">=14.16"
"node": ">=18"
},
"scripts": {
"test": "xo && ava && tsd"
Expand Down Expand Up @@ -42,11 +42,11 @@
"hrtime"
],
"dependencies": {
"parse-ms": "^3.0.0"
"parse-ms": "^4.0.0"
},
"devDependencies": {
"ava": "^4.3.0",
"tsd": "^0.20.0",
"xo": "^0.49.0"
"ava": "^6.0.1",
"tsd": "^0.30.4",
"xo": "^0.56.0"
}
}
221 changes: 116 additions & 105 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ test('prettify milliseconds', t => {
t.is(prettyMilliseconds(1000 * 60 * 67 * 24 * 465), '1y 154d 6h');
t.is(prettyMilliseconds(119_999), '1m 59.9s');
t.is(prettyMilliseconds(120_000), '2m');
t.is(prettyMilliseconds(Number.MAX_SAFE_INTEGER), '285616y 151d 8h 59m 0.9s');
t.is(prettyMilliseconds(Number.MAX_VALUE), '5700447535712568547083700427941645003808085225292279557374304680873482979681895890593452082909683139015032646149857723394516742095667500822861020052921074432454921864096959420926519725467567456931340929884912090099277441972878147362726992943838905852030073647982034630974035871792165820638724934142y 218d 8h 8m 48s');
});

test('have a compact option', t => {
Expand Down Expand Up @@ -62,24 +64,24 @@ test('have a keepDecimalsOnWholeSeconds option', t => {
});

test('have a verbose option', t => {
const fn = milliseconds => prettyMilliseconds(milliseconds, {verbose: true});
const format = milliseconds => prettyMilliseconds(milliseconds, {verbose: true});

t.is(fn(0), '0 milliseconds');
t.is(fn(0.1), '1 millisecond');
t.is(fn(1), '1 millisecond');
t.is(fn(1000), '1 second');
t.is(fn(1000 + 400), '1.4 seconds');
t.is(fn((1000 * 2) + 400), '2.4 seconds');
t.is(fn(1000 * 5), '5 seconds');
t.is(fn(1000 * 55), '55 seconds');
t.is(fn(1000 * 67), '1 minute 7 seconds');
t.is(fn(1000 * 60 * 5), '5 minutes');
t.is(fn(1000 * 60 * 67), '1 hour 7 minutes');
t.is(fn(1000 * 60 * 60 * 12), '12 hours');
t.is(fn(1000 * 60 * 60 * 40), '1 day 16 hours');
t.is(fn(1000 * 60 * 60 * 999), '41 days 15 hours');
t.is(fn(1000 * 60 * 60 * 24 * 465), '1 year 100 days');
t.is(fn(1000 * 60 * 67 * 24 * 465), '1 year 154 days 6 hours');
t.is(format(0), '0 milliseconds');
t.is(format(0.1), '1 millisecond');
t.is(format(1), '1 millisecond');
t.is(format(1000), '1 second');
t.is(format(1000 + 400), '1.4 seconds');
t.is(format((1000 * 2) + 400), '2.4 seconds');
t.is(format(1000 * 5), '5 seconds');
t.is(format(1000 * 55), '55 seconds');
t.is(format(1000 * 67), '1 minute 7 seconds');
t.is(format(1000 * 60 * 5), '5 minutes');
t.is(format(1000 * 60 * 67), '1 hour 7 minutes');
t.is(format(1000 * 60 * 60 * 12), '12 hours');
t.is(format(1000 * 60 * 60 * 40), '1 day 16 hours');
t.is(format(1000 * 60 * 60 * 999), '41 days 15 hours');
t.is(format(1000 * 60 * 60 * 24 * 465), '1 year 100 days');
t.is(format(1000 * 60 * 67 * 24 * 465), '1 year 154 days 6 hours');
});

test('have a separateMilliseconds option', t => {
Expand All @@ -100,24 +102,24 @@ test('have a formatSubMilliseconds option', t => {
});

test('work with verbose and compact options', t => {
const fn = milliseconds => prettyMilliseconds(milliseconds, {
const format = milliseconds => prettyMilliseconds(milliseconds, {
verbose: true,
compact: true,
});

t.is(fn(1000), '1 second');
t.is(fn(1000 + 400), '1 second');
t.is(fn((1000 * 2) + 400), '2 seconds');
t.is(fn(1000 * 5), '5 seconds');
t.is(fn(1000 * 55), '55 seconds');
t.is(fn(1000 * 67), '1 minute');
t.is(fn(1000 * 60 * 5), '5 minutes');
t.is(fn(1000 * 60 * 67), '1 hour');
t.is(fn(1000 * 60 * 60 * 12), '12 hours');
t.is(fn(1000 * 60 * 60 * 40), '1 day');
t.is(fn(1000 * 60 * 60 * 999), '41 days');
t.is(fn(1000 * 60 * 60 * 24 * 465), '1 year');
t.is(fn(1000 * 60 * 67 * 24 * 750), '2 years');
t.is(format(1000), '1 second');
t.is(format(1000 + 400), '1 second');
t.is(format((1000 * 2) + 400), '2 seconds');
t.is(format(1000 * 5), '5 seconds');
t.is(format(1000 * 55), '55 seconds');
t.is(format(1000 * 67), '1 minute');
t.is(format(1000 * 60 * 5), '5 minutes');
t.is(format(1000 * 60 * 67), '1 hour');
t.is(format(1000 * 60 * 60 * 12), '12 hours');
t.is(format(1000 * 60 * 60 * 40), '1 day');
t.is(format(1000 * 60 * 60 * 999), '41 days');
t.is(format(1000 * 60 * 60 * 24 * 465), '1 year');
t.is(format(1000 * 60 * 67 * 24 * 750), '2 years');
});

test('work with verbose and unitCount options', t => {
Expand All @@ -130,29 +132,29 @@ test('work with verbose and unitCount options', t => {
});

test('work with verbose and secondsDecimalDigits options', t => {
const fn = milliseconds => prettyMilliseconds(milliseconds, {
const format = milliseconds => prettyMilliseconds(milliseconds, {
verbose: true,
secondsDecimalDigits: 4,
});

t.is(fn(1000), '1 second');
t.is(fn(1000 + 400), '1.4000 seconds');
t.is(fn((1000 * 2) + 400), '2.4000 seconds');
t.is(fn((1000 * 5) + 254), '5.2540 seconds');
t.is(fn(33_333), '33.3330 seconds');
t.is(format(1000), '1 second');
t.is(format(1000 + 400), '1.4000 seconds');
t.is(format((1000 * 2) + 400), '2.4000 seconds');
t.is(format((1000 * 5) + 254), '5.2540 seconds');
t.is(format(33_333), '33.3330 seconds');
});

test('work with verbose and millisecondsDecimalDigits options', t => {
const fn = milliseconds => prettyMilliseconds(milliseconds, {
const format = milliseconds => prettyMilliseconds(milliseconds, {
verbose: true,
millisecondsDecimalDigits: 4,
});

t.is(fn(1), '1.0000 millisecond');
t.is(fn(1 + 0.4), '1.4000 milliseconds');
t.is(fn((1 * 2) + 0.4), '2.4000 milliseconds');
t.is(fn((1 * 5) + 0.254), '5.2540 milliseconds');
t.is(fn(33.333), '33.3330 milliseconds');
t.is(format(1), '1.0000 millisecond');
t.is(format(1 + 0.4), '1.4000 milliseconds');
t.is(format((1 * 2) + 0.4), '2.4000 milliseconds');
t.is(format((1 * 5) + 0.254), '5.2540 milliseconds');
t.is(format(33.333), '33.3330 milliseconds');
});

test('work with verbose and formatSubMilliseconds options', t => {
Expand Down Expand Up @@ -218,82 +220,91 @@ test('throw on invalid', t => {
});

test('properly rounds milliseconds with secondsDecimalDigits', t => {
const fn = milliseconds =>
const format = milliseconds =>
prettyMilliseconds(milliseconds, {
verbose: true,
secondsDecimalDigits: 0,
});
t.is(fn(3 * 60 * 1000), '3 minutes');
t.is(fn((3 * 60 * 1000) - 1), '2 minutes 59 seconds');
t.is(fn(365 * 24 * 3600 * 1e3), '1 year');
t.is(fn((365 * 24 * 3600 * 1e3) - 1), '364 days 23 hours 59 minutes 59 seconds');
t.is(fn(24 * 3600 * 1e3), '1 day');
t.is(fn((24 * 3600 * 1e3) - 1), '23 hours 59 minutes 59 seconds');
t.is(fn(3600 * 1e3), '1 hour');
t.is(fn((3600 * 1e3) - 1), '59 minutes 59 seconds');
t.is(fn(2 * 3600 * 1e3), '2 hours');
t.is(fn((2 * 3600 * 1e3) - 1), '1 hour 59 minutes 59 seconds');
t.is(format(3 * 60 * 1000), '3 minutes');
t.is(format((3 * 60 * 1000) - 1), '2 minutes 59 seconds');
t.is(format(365 * 24 * 3600 * 1e3), '1 year');
t.is(format((365 * 24 * 3600 * 1e3) - 1), '364 days 23 hours 59 minutes 59 seconds');
t.is(format(24 * 3600 * 1e3), '1 day');
t.is(format((24 * 3600 * 1e3) - 1), '23 hours 59 minutes 59 seconds');
t.is(format(3600 * 1e3), '1 hour');
t.is(format((3600 * 1e3) - 1), '59 minutes 59 seconds');
t.is(format(2 * 3600 * 1e3), '2 hours');
t.is(format((2 * 3600 * 1e3) - 1), '1 hour 59 minutes 59 seconds');
});

test('`colonNotation` option', t => {
const format = (milliseconds, options) =>
prettyMilliseconds(milliseconds, {
colonNotation: true,
...options,
});
// Default formats
t.is(prettyMilliseconds(1000, {colonNotation: true}), '0:01');
t.is(prettyMilliseconds(1543, {colonNotation: true}), '0:01.5');
t.is(prettyMilliseconds(1000 * 60, {colonNotation: true}), '1:00');
t.is(prettyMilliseconds(1000 * 90, {colonNotation: true}), '1:30');
t.is(prettyMilliseconds(95_543, {colonNotation: true}), '1:35.5');
t.is(prettyMilliseconds((1000 * 60 * 10) + 543, {colonNotation: true}), '10:00.5');
t.is(prettyMilliseconds((1000 * 60 * 59) + (1000 * 59) + 543, {colonNotation: true}), '59:59.5');
t.is(prettyMilliseconds((1000 * 60 * 60 * 15) + (1000 * 60 * 59) + (1000 * 59) + 543, {colonNotation: true}), '15:59:59.5');
t.is(format(1000), '0:01');
t.is(format(1543), '0:01.5');
t.is(format(1000 * 60), '1:00');
t.is(format(1000 * 90), '1:30');
t.is(format(95_543), '1:35.5');
t.is(format((1000 * 60 * 10) + 543), '10:00.5');
t.is(format((1000 * 60 * 59) + (1000 * 59) + 543), '59:59.5');
t.is(format((1000 * 60 * 60 * 15) + (1000 * 60 * 59) + (1000 * 59) + 543), '15:59:59.5');

// Together with `secondsDecimalDigits`
t.is(prettyMilliseconds(999, {colonNotation: true, secondsDecimalDigits: 0}), '0:00');
t.is(prettyMilliseconds(999, {colonNotation: true, secondsDecimalDigits: 1}), '0:00.9');
t.is(prettyMilliseconds(999, {colonNotation: true, secondsDecimalDigits: 2}), '0:00.99');
t.is(prettyMilliseconds(999, {colonNotation: true, secondsDecimalDigits: 3}), '0:00.999');
t.is(prettyMilliseconds(1000, {colonNotation: true, secondsDecimalDigits: 0}), '0:01');
t.is(prettyMilliseconds(1000, {colonNotation: true, secondsDecimalDigits: 1}), '0:01');
t.is(prettyMilliseconds(1000, {colonNotation: true, secondsDecimalDigits: 2}), '0:01');
t.is(prettyMilliseconds(1000, {colonNotation: true, secondsDecimalDigits: 3}), '0:01');
t.is(prettyMilliseconds(1001, {colonNotation: true, secondsDecimalDigits: 0}), '0:01');
t.is(prettyMilliseconds(1001, {colonNotation: true, secondsDecimalDigits: 1}), '0:01');
t.is(prettyMilliseconds(1001, {colonNotation: true, secondsDecimalDigits: 2}), '0:01');
t.is(prettyMilliseconds(1001, {colonNotation: true, secondsDecimalDigits: 3}), '0:01.001');
t.is(prettyMilliseconds(1543, {colonNotation: true, secondsDecimalDigits: 0}), '0:01');
t.is(prettyMilliseconds(1543, {colonNotation: true, secondsDecimalDigits: 1}), '0:01.5');
t.is(prettyMilliseconds(1543, {colonNotation: true, secondsDecimalDigits: 2}), '0:01.54');
t.is(prettyMilliseconds(1543, {colonNotation: true, secondsDecimalDigits: 3}), '0:01.543');
t.is(prettyMilliseconds(95_543, {colonNotation: true, secondsDecimalDigits: 0}), '1:35');
t.is(prettyMilliseconds(95_543, {colonNotation: true, secondsDecimalDigits: 1}), '1:35.5');
t.is(prettyMilliseconds(95_543, {colonNotation: true, secondsDecimalDigits: 2}), '1:35.54');
t.is(prettyMilliseconds(95_543, {colonNotation: true, secondsDecimalDigits: 3}), '1:35.543');
t.is(prettyMilliseconds((1000 * 60 * 10) + 543, {colonNotation: true, secondsDecimalDigits: 3}), '10:00.543');
t.is(prettyMilliseconds((1000 * 60 * 60 * 15) + (1000 * 60 * 59) + (1000 * 59) + 543, {colonNotation: true, secondsDecimalDigits: 3}), '15:59:59.543');
t.is(format(999, {secondsDecimalDigits: 0}), '0:00');
t.is(format(999, {secondsDecimalDigits: 1}), '0:00.9');
t.is(format(999, {secondsDecimalDigits: 2}), '0:00.99');
t.is(format(999, {secondsDecimalDigits: 3}), '0:00.999');
t.is(format(1000, {secondsDecimalDigits: 0}), '0:01');
t.is(format(1000, {secondsDecimalDigits: 1}), '0:01');
t.is(format(1000, {secondsDecimalDigits: 2}), '0:01');
t.is(format(1000, {secondsDecimalDigits: 3}), '0:01');
t.is(format(1001, {secondsDecimalDigits: 0}), '0:01');
t.is(format(1001, {secondsDecimalDigits: 1}), '0:01');
t.is(format(1001, {secondsDecimalDigits: 2}), '0:01');
t.is(format(1001, {secondsDecimalDigits: 3}), '0:01.001');
t.is(format(1543, {secondsDecimalDigits: 0}), '0:01');
t.is(format(1543, {secondsDecimalDigits: 1}), '0:01.5');
t.is(format(1543, {secondsDecimalDigits: 2}), '0:01.54');
t.is(format(1543, {secondsDecimalDigits: 3}), '0:01.543');
t.is(format(95_543, {secondsDecimalDigits: 0}), '1:35');
t.is(format(95_543, {secondsDecimalDigits: 1}), '1:35.5');
t.is(format(95_543, {secondsDecimalDigits: 2}), '1:35.54');
t.is(format(95_543, {secondsDecimalDigits: 3}), '1:35.543');
t.is(format((1000 * 60 * 10) + 543, {secondsDecimalDigits: 3}), '10:00.543');
t.is(format((1000 * 60 * 60 * 15) + (1000 * 60 * 59) + (1000 * 59) + 543, {secondsDecimalDigits: 3}), '15:59:59.543');

// Together with `keepDecimalsOnWholeSeconds`
t.is(prettyMilliseconds(999, {colonNotation: true, secondsDecimalDigits: 0, keepDecimalsOnWholeSeconds: true}), '0:00');
t.is(prettyMilliseconds(999, {colonNotation: true, secondsDecimalDigits: 1, keepDecimalsOnWholeSeconds: true}), '0:00.9');
t.is(prettyMilliseconds(999, {colonNotation: true, secondsDecimalDigits: 2, keepDecimalsOnWholeSeconds: true}), '0:00.99');
t.is(prettyMilliseconds(999, {colonNotation: true, secondsDecimalDigits: 3, keepDecimalsOnWholeSeconds: true}), '0:00.999');
t.is(prettyMilliseconds(1000, {colonNotation: true, keepDecimalsOnWholeSeconds: true}), '0:01.0');
t.is(prettyMilliseconds(1000, {colonNotation: true, secondsDecimalDigits: 0, keepDecimalsOnWholeSeconds: true}), '0:01');
t.is(prettyMilliseconds(1000, {colonNotation: true, secondsDecimalDigits: 1, keepDecimalsOnWholeSeconds: true}), '0:01.0');
t.is(prettyMilliseconds(1000, {colonNotation: true, secondsDecimalDigits: 3, keepDecimalsOnWholeSeconds: true}), '0:01.000');
t.is(prettyMilliseconds(1000 * 90, {colonNotation: true, keepDecimalsOnWholeSeconds: true}), '1:30.0');
t.is(prettyMilliseconds(1000 * 90, {colonNotation: true, secondsDecimalDigits: 3, keepDecimalsOnWholeSeconds: true}), '1:30.000');
t.is(prettyMilliseconds(1000 * 60 * 10, {colonNotation: true, secondsDecimalDigits: 3, keepDecimalsOnWholeSeconds: true}), '10:00.000');
t.is(format(999, {secondsDecimalDigits: 0, keepDecimalsOnWholeSeconds: true}), '0:00');
t.is(format(999, {secondsDecimalDigits: 1, keepDecimalsOnWholeSeconds: true}), '0:00.9');
t.is(format(999, {secondsDecimalDigits: 2, keepDecimalsOnWholeSeconds: true}), '0:00.99');
t.is(format(999, {secondsDecimalDigits: 3, keepDecimalsOnWholeSeconds: true}), '0:00.999');
t.is(format(1000, {keepDecimalsOnWholeSeconds: true}), '0:01.0');
t.is(format(1000, {secondsDecimalDigits: 0, keepDecimalsOnWholeSeconds: true}), '0:01');
t.is(format(1000, {secondsDecimalDigits: 1, keepDecimalsOnWholeSeconds: true}), '0:01.0');
t.is(format(1000, {secondsDecimalDigits: 3, keepDecimalsOnWholeSeconds: true}), '0:01.000');
t.is(format(1000 * 90, {keepDecimalsOnWholeSeconds: true}), '1:30.0');
t.is(format(1000 * 90, {secondsDecimalDigits: 3, keepDecimalsOnWholeSeconds: true}), '1:30.000');
t.is(format(1000 * 60 * 10, {secondsDecimalDigits: 3, keepDecimalsOnWholeSeconds: true}), '10:00.000');

// Together with `unitCount`
t.is(prettyMilliseconds(1000 * 90, {colonNotation: true, secondsDecimalDigits: 0, unitCount: 1}), '1');
t.is(prettyMilliseconds(1000 * 90, {colonNotation: true, secondsDecimalDigits: 0, unitCount: 2}), '1:30');
t.is(prettyMilliseconds(1000 * 60 * 90, {colonNotation: true, secondsDecimalDigits: 0, unitCount: 3}), '1:30:00');
t.is(prettyMilliseconds(95_543, {colonNotation: true, secondsDecimalDigits: 1, unitCount: 1}), '1');
t.is(prettyMilliseconds(95_543, {colonNotation: true, secondsDecimalDigits: 1, unitCount: 2}), '1:35.5');
t.is(prettyMilliseconds(95_543 + (1000 * 60 * 60), {colonNotation: true, secondsDecimalDigits: 1, unitCount: 3}), '1:01:35.5');
t.is(format(1000 * 90, {secondsDecimalDigits: 0, unitCount: 1}), '1');
t.is(format(1000 * 90, {secondsDecimalDigits: 0, unitCount: 2}), '1:30');
t.is(format(1000 * 60 * 90, {secondsDecimalDigits: 0, unitCount: 3}), '1:30:00');
t.is(format(95_543, {secondsDecimalDigits: 1, unitCount: 1}), '1');
t.is(format(95_543, {secondsDecimalDigits: 1, unitCount: 2}), '1:35.5');
t.is(format(95_543 + (1000 * 60 * 60), {secondsDecimalDigits: 1, unitCount: 3}), '1:01:35.5');

// Make sure incompatible options fall back to `colonNotation`
t.is(prettyMilliseconds((1000 * 60 * 59) + (1000 * 59) + 543, {colonNotation: true, formatSubMilliseconds: true}), '59:59.5');
t.is(prettyMilliseconds((1000 * 60 * 59) + (1000 * 59) + 543, {colonNotation: true, separateMilliseconds: true}), '59:59.5');
t.is(prettyMilliseconds((1000 * 60 * 59) + (1000 * 59) + 543, {colonNotation: true, verbose: true}), '59:59.5');
t.is(prettyMilliseconds((1000 * 60 * 59) + (1000 * 59) + 543, {colonNotation: true, compact: true}), '59:59.5');
t.is(format((1000 * 60 * 59) + (1000 * 59) + 543, {formatSubMilliseconds: true}), '59:59.5');
t.is(format((1000 * 60 * 59) + (1000 * 59) + 543, {separateMilliseconds: true}), '59:59.5');
t.is(format((1000 * 60 * 59) + (1000 * 59) + 543, {verbose: true}), '59:59.5');
t.is(format((1000 * 60 * 59) + (1000 * 59) + 543, {compact: true}), '59:59.5');

// Big numbers
t.is(format(Number.MAX_SAFE_INTEGER), '285616:151:08:59:00.9');
t.is(format(Number.MAX_VALUE), '5700447535712568547083700427941645003808085225292279557374304680873482979681895890593452082909683139015032646149857723394516742095667500822861020052921074432454921864096959420926519725467567456931340929884912090099277441972878147362726992943838905852030073647982034630974035871792165820638724934142:218:08:08:48');
});