From 20ff8550dfd3125b515d6a8d1633babb26f95045 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 14 Jul 2020 10:25:44 -0400 Subject: [PATCH] fix format duration rounding days error Signed-off-by: Sebastian Malton --- .../utils/__tests__/formatDuration.test.ts | 47 +++++++++++++++++++ src/renderer/utils/formatDuration.ts | 37 +++++++++------ 2 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 src/renderer/utils/__tests__/formatDuration.test.ts diff --git a/src/renderer/utils/__tests__/formatDuration.test.ts b/src/renderer/utils/__tests__/formatDuration.test.ts new file mode 100644 index 0000000000..bad84c4af1 --- /dev/null +++ b/src/renderer/utils/__tests__/formatDuration.test.ts @@ -0,0 +1,47 @@ +import { formatDuration } from "../formatDuration"; +import { min } from "moment"; + +const second = 1000; +const minute = 60 * second; +const hour = 60 * minute; +const day = 24 * hour; +const week = 7 * day; + +describe("human format durations", () => { + test("long formatted durations less than 24 hours long shouldn't have a 'd' component", () => { + const res = formatDuration(19 * 60 * 60 * 1000, false); + + expect(res).not.toContain("d"); + expect(res).toBe("19h"); + }); + + test("long formatted durations more than a week have correct day count", () => { + const res = formatDuration(2 * week + 2 * day, false); + + expect(res).toBe("2w 2d"); + }); + + test("durations > 1/2 week shouldn't show 1w has passed", () => { + const res = formatDuration(5 * 24 * 60 * 60 * 1000, false); + + expect(res).not.toContain("w"); + expect(res).toBe("5d"); + }); + + test("durations shouldn't include zero magnitude parts", () => { + const res = formatDuration(6 * day + 2 * minute, false); + + expect(res).not.toContain("h"); + expect(res).toBe("6d 2m"); + }); + + test("seconds are ignored unless they are significant (< 1m)", () => { + const insignificant = formatDuration(1 * hour + 2 * minute + 31 * second, false); + + expect(insignificant).not.toContain("s"); + expect(insignificant).toBe("1h 2m"); + + const significant = formatDuration(31 * second, false); + expect(significant).toBe("31s"); + }); +}); diff --git a/src/renderer/utils/formatDuration.ts b/src/renderer/utils/formatDuration.ts index 48107d3c0b..fc11636c79 100644 --- a/src/renderer/utils/formatDuration.ts +++ b/src/renderer/utils/formatDuration.ts @@ -1,24 +1,31 @@ -// Formatting date duration in shorten format, e.g. "2d", or "25m" - import moment from "moment"; +const suffixes = ["w", "d", "h", "m", "s"]; + +/** + * This function formats durations in a more human readable form. + * @param timeValue the duration in milliseconds to format + * @param compact when true, only the largest non-zero time frame will be returned + */ export function formatDuration(timeValue: number, compact: boolean) { - let result = ""; - const duration = moment.duration(timeValue); - const suffixes = ["d", "h", "m"]; + const duration = moment.duration(timeValue, "milliseconds"); const durationValues = [ - Math.round(duration.asDays()), + Math.floor(duration.asWeeks()), + Math.floor(duration.asDays()) % 7, duration.hours(), duration.minutes(), + duration.seconds(), ]; - durationValues.forEach((value, index) => { - if (value) result += value + suffixes[index] + " "; - }); + + const meaningfulValues = durationValues + .map((a, i): [number, string] => [a, suffixes[i]]) + .filter(([dur, _suf]) => dur > 0) + .filter(([_dur, suf], i) => i === 0 || suf !== "s") // remove seconds, unless it is the only one + .map(([dur, suf]) => dur + suf); + if (compact) { - result = result.split(" ")[0]; + return meaningfulValues[0]; } - if (!result) { - return "<1m"; - } - return result; -} \ No newline at end of file + + return meaningfulValues.join(" "); +}