From b9b1dd73f58c3ee66161fd316299c0a6772b0a0d Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 21 Feb 2023 01:08:07 +0100 Subject: taler-util: parse duration strings --- packages/taler-util/src/time.test.ts | 39 ++++++++++++++++++++++++++++++++ packages/taler-util/src/time.ts | 43 ++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 packages/taler-util/src/time.test.ts diff --git a/packages/taler-util/src/time.test.ts b/packages/taler-util/src/time.test.ts new file mode 100644 index 000000000..876b35b9a --- /dev/null +++ b/packages/taler-util/src/time.test.ts @@ -0,0 +1,39 @@ +/* + This file is part of GNU Taler + (C) 2019 GNUnet e.V. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +import test from "ava"; +import { Duration } from "./time.js"; + +test("duration parsing", (t) => { + const d1 = Duration.fromPrettyString("1h"); + t.deepEqual(d1.d_ms, 60 * 60 * 1000); + + const d2 = Duration.fromPrettyString(" 2h 1s 3m"); + t.deepEqual(d2.d_ms, 2 * 60 * 60 * 1000 + 3 * 60 * 1000 + 1000); + + t.throws(() => { + Duration.fromPrettyString("5g"); + }); + t.throws(() => { + Duration.fromPrettyString("s"); + }); + t.throws(() => { + Duration.fromPrettyString("s5"); + }); + t.throws(() => { + Duration.fromPrettyString("5 5 s"); + }); +}); diff --git a/packages/taler-util/src/time.ts b/packages/taler-util/src/time.ts index 21963ee6b..8b4f4cac3 100644 --- a/packages/taler-util/src/time.ts +++ b/packages/taler-util/src/time.ts @@ -113,6 +113,49 @@ export namespace Duration { return { d_ms: deadline.t_ms - now.t_ms }; } + export function fromPrettyString(s: string): Duration { + let dMs = 0; + let currentNum = ""; + let parsingNum = true; + for (let i = 0; i < s.length; i++) { + const cc = s.charCodeAt(i); + if (cc >= "0".charCodeAt(0) && cc <= "9".charCodeAt(0)) { + if (!parsingNum) { + throw Error("invalid duration, unexpected number"); + } + currentNum += s[i]; + continue; + } + if (s[i] == " ") { + if (currentNum != "") { + parsingNum = false; + } + continue; + } + + if (currentNum == "") { + throw Error("invalid duration, missing number"); + } + + if (s[i] === "s") { + dMs += 1000 * Number.parseInt(currentNum, 10); + } else if (s[i] === "m") { + dMs += 60 * 1000 * Number.parseInt(currentNum, 10); + } else if (s[i] === "h") { + dMs += 60 * 60 * 1000 * Number.parseInt(currentNum, 10); + } else if (s[i] === "d") { + dMs += 24 * 60 * 60 * 1000 * Number.parseInt(currentNum, 10); + } else { + throw Error("invalid duration, unsupported unit"); + } + currentNum = ""; + parsingNum = true; + } + return { + d_ms: dMs, + }; + } + export function max(d1: Duration, d2: Duration): Duration { return durationMax(d1, d2); } -- cgit v1.2.3