diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d50ada6..346585c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -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 diff --git a/index.d.ts b/index.d.ts index 00eeae3..ef284f5 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,4 +1,4 @@ -export interface Options { +export type Options = { /** Number of digits to appear after the seconds decimal point. @@ -75,7 +75,7 @@ export interface Options { @default false */ readonly colonNotation?: boolean; -} +}; /** Convert milliseconds to a human readable string: `1337000000` → `15d 11h 23m 20s`. diff --git a/index.js b/index.js index dd9a31d..c0f433e 100644 --- a/index.js +++ b/index.js @@ -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; @@ -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; } @@ -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'); @@ -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), diff --git a/package.json b/package.json index b543e27..2d7c40d 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "exports": "./index.js", "types": "./index.d.ts", "engines": { - "node": ">=14.16" + "node": ">=18" }, "scripts": { "test": "xo && ava && tsd" @@ -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" } } diff --git a/test.js b/test.js index 4ca5a42..e3b944e 100644 --- a/test.js +++ b/test.js @@ -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 => { @@ -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 => { @@ -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 => { @@ -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 => { @@ -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'); });