Improve Chat.toDurationString

- Default precision is now 3.

  (Instead of "3 months 25 days 17 hours 46 minutes 40 seconds", it'll
	say "3 months 25 days 17 hours". You can still set the precision to
	`Infinity` if you actually prefer that.)

- Now displays "forever" for Infinity or overflow durations

- No longer skips blank precision levels

  (Shows "3 hours 0 minutes 10 seconds" instead of
	"3 hours  10 seconds")
This commit is contained in:
Guangcong Luo 2020-10-21 12:23:02 +01:00
parent ef6cad7c9d
commit d6eeb197c1
2 changed files with 12 additions and 3 deletions

View File

@ -1877,10 +1877,12 @@ export const Chat = new class {
* options.hhmmss = true will instead report the duration in 00:00:00 format
*
*/
toDurationString(val: number, options: {hhmmss?: any, precision?: number} = {}) {
toDurationString(val: number, options: {hhmmss?: boolean, precision?: number} = {}) {
// TODO: replace by Intl.DurationFormat or equivalent when it becomes available (ECMA-402)
// https://github.com/tc39/ecma402/issues/47
const date = new Date(+val);
if (isNaN(date.getTime())) return 'forever';
const parts = [
date.getUTCFullYear() - 1970, date.getUTCMonth(), date.getUTCDate() - 1,
date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(),
@ -1888,11 +1890,12 @@ export const Chat = new class {
const roundingBoundaries = [6, 15, 12, 30, 30];
const unitNames = ["second", "minute", "hour", "day", "month", "year"];
const positiveIndex = parts.findIndex(elem => elem > 0);
const precision = (options?.precision ? options.precision : parts.length);
const precision = (options?.precision ? options.precision : 3);
if (options?.hhmmss) {
const str = parts.slice(positiveIndex).map(value => value < 10 ? "0" + value : "" + value).join(":");
return str.length === 2 ? "00:" + str : str;
}
// round least significant displayed unit
if (positiveIndex + precision < parts.length && precision > 0 && positiveIndex >= 0) {
if (parts[positiveIndex + precision] >= roundingBoundaries[positiveIndex + precision - 1]) {
@ -1902,7 +1905,7 @@ export const Chat = new class {
return parts
.slice(positiveIndex)
.reverse()
.map((value, index) => value ? value + " " + unitNames[index] + (value > 1 ? "s" : "") : "")
.map((value, index) => `${value} ${unitNames[index]}${value !== 1 ? "s" : ""}`)
.reverse()
.slice(0, precision)
.join(" ")

View File

@ -101,4 +101,10 @@ describe('Chat', function () {
`a<br />b<br />c`
);
});
it('should run toDurationString correctly', function () {
assert(Chat.toDurationString(1e50));
assert(!Chat.toDurationString(10000000 * 24 * 60 * 60 * 1000).includes(' '));
});
});