From a19ff5aef52209abeca1ebc13c59704124fa1006 Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Sun, 26 Mar 2023 17:52:18 -0400 Subject: [PATCH] Add milliseconds support for duration sensors (#15895) --- src/common/datetime/duration.ts | 25 +++++++++++-------- .../datetime/milliseconds_to_duration.ts | 25 +++++++++++++++++++ src/common/entity/compute_state_display.ts | 7 ++++-- test/common/datetime/duration.ts | 13 ++++++++++ .../datetime/milliseconds_to_duration_test.ts | 18 +++++++++++++ 5 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 src/common/datetime/milliseconds_to_duration.ts create mode 100644 test/common/datetime/milliseconds_to_duration_test.ts diff --git a/src/common/datetime/duration.ts b/src/common/datetime/duration.ts index 2d6c46ff87..36fef1902a 100644 --- a/src/common/datetime/duration.ts +++ b/src/common/datetime/duration.ts @@ -1,16 +1,19 @@ -import secondsToDuration from "./seconds_to_duration"; +import millisecondsToDuration from "./milliseconds_to_duration"; -const DAY_IN_SECONDS = 86400; -const HOUR_IN_SECONDS = 3600; -const MINUTE_IN_SECONDS = 60; +const DAY_IN_MILLISECONDS = 86400000; +const HOUR_IN_MILLISECONDS = 3600000; +const MINUTE_IN_MILLISECONDS = 60000; +const SECOND_IN_MILLISECONDS = 1000; -export const UNIT_TO_SECOND_CONVERT = { - s: 1, - min: MINUTE_IN_SECONDS, - h: HOUR_IN_SECONDS, - d: DAY_IN_SECONDS, +export const UNIT_TO_MILLISECOND_CONVERT = { + ms: 1, + s: SECOND_IN_MILLISECONDS, + min: MINUTE_IN_MILLISECONDS, + h: HOUR_IN_MILLISECONDS, + d: DAY_IN_MILLISECONDS, }; export const formatDuration = (duration: string, units: string): string => - secondsToDuration(parseFloat(duration) * UNIT_TO_SECOND_CONVERT[units]) || - "0"; + millisecondsToDuration( + parseFloat(duration) * UNIT_TO_MILLISECOND_CONVERT[units] + ) || "0"; diff --git a/src/common/datetime/milliseconds_to_duration.ts b/src/common/datetime/milliseconds_to_duration.ts new file mode 100644 index 0000000000..384a8a7707 --- /dev/null +++ b/src/common/datetime/milliseconds_to_duration.ts @@ -0,0 +1,25 @@ +const leftPad = (num: number, digits = 2) => { + let paddedNum = "" + num; + for (let i = 1; i < digits; i++) { + paddedNum = parseInt(paddedNum) < 10 ** i ? `0${paddedNum}` : paddedNum; + } + return paddedNum; +}; + +export default function millisecondsToDuration(d: number) { + const h = Math.floor(d / 1000 / 3600); + const m = Math.floor(((d / 1000) % 3600) / 60); + const s = Math.floor(((d / 1000) % 3600) % 60); + const ms = Math.floor(d % 1000); + + if (h > 0) { + return `${h}:${leftPad(m)}:${leftPad(s)}`; + } + if (m > 0) { + return `${m}:${leftPad(s)}`; + } + if (s > 0 || ms > 0) { + return `${s}${ms > 0 ? `.${leftPad(ms, 3)}` : ``}`; + } + return null; +} diff --git a/src/common/entity/compute_state_display.ts b/src/common/entity/compute_state_display.ts index ee1326f291..b0a10f9057 100644 --- a/src/common/entity/compute_state_display.ts +++ b/src/common/entity/compute_state_display.ts @@ -7,7 +7,10 @@ import { UPDATE_SUPPORT_PROGRESS, } from "../../data/update"; import { HomeAssistant } from "../../types"; -import { formatDuration, UNIT_TO_SECOND_CONVERT } from "../datetime/duration"; +import { + formatDuration, + UNIT_TO_MILLISECOND_CONVERT, +} from "../datetime/duration"; import { formatDate } from "../datetime/format_date"; import { formatDateTime } from "../datetime/format_date_time"; import { formatTime } from "../datetime/format_time"; @@ -57,7 +60,7 @@ export const computeStateDisplayFromEntityAttributes = ( if ( attributes.device_class === "duration" && attributes.unit_of_measurement && - UNIT_TO_SECOND_CONVERT[attributes.unit_of_measurement] + UNIT_TO_MILLISECOND_CONVERT[attributes.unit_of_measurement] ) { try { return formatDuration(state, attributes.unit_of_measurement); diff --git a/test/common/datetime/duration.ts b/test/common/datetime/duration.ts index 3e3a037451..32565316a3 100644 --- a/test/common/datetime/duration.ts +++ b/test/common/datetime/duration.ts @@ -4,7 +4,20 @@ import { formatDuration } from "../../../src/common/datetime/duration"; describe("formatDuration", () => { it("works", () => { + assert.strictEqual(formatDuration("0", "ms"), "0"); + assert.strictEqual(formatDuration("1", "ms"), "0.001"); + assert.strictEqual(formatDuration("10", "ms"), "0.010"); + assert.strictEqual(formatDuration("100", "ms"), "0.100"); + assert.strictEqual(formatDuration("1000", "ms"), "1"); + assert.strictEqual(formatDuration("1001", "ms"), "1.001"); + assert.strictEqual(formatDuration("65000", "ms"), "1:05"); + assert.strictEqual(formatDuration("3665000", "ms"), "1:01:05"); + assert.strictEqual(formatDuration("39665050", "ms"), "11:01:05"); + assert.strictEqual(formatDuration("932093000", "ms"), "258:54:53"); + assert.strictEqual(formatDuration("0", "s"), "0"); + assert.strictEqual(formatDuration("1", "s"), "1"); + assert.strictEqual(formatDuration("1.1", "s"), "1.100"); assert.strictEqual(formatDuration("65", "s"), "1:05"); assert.strictEqual(formatDuration("3665", "s"), "1:01:05"); assert.strictEqual(formatDuration("39665", "s"), "11:01:05"); diff --git a/test/common/datetime/milliseconds_to_duration_test.ts b/test/common/datetime/milliseconds_to_duration_test.ts new file mode 100644 index 0000000000..3d8089cd36 --- /dev/null +++ b/test/common/datetime/milliseconds_to_duration_test.ts @@ -0,0 +1,18 @@ +import { assert } from "chai"; + +import millisecondsToDuration from "../../../src/common/datetime/milliseconds_to_duration"; + +describe("millisecondsToDuration", () => { + it("works", () => { + assert.strictEqual(millisecondsToDuration(0), null); + assert.strictEqual(millisecondsToDuration(1), "0.001"); + assert.strictEqual(millisecondsToDuration(10), "0.010"); + assert.strictEqual(millisecondsToDuration(100), "0.100"); + assert.strictEqual(millisecondsToDuration(1000), "1"); + assert.strictEqual(millisecondsToDuration(1001), "1.001"); + assert.strictEqual(millisecondsToDuration(65000), "1:05"); + assert.strictEqual(millisecondsToDuration(3665000), "1:01:05"); + assert.strictEqual(millisecondsToDuration(39665050), "11:01:05"); + assert.strictEqual(millisecondsToDuration(932093000), "258:54:53"); + }); +});