util.human.io: Don't accept ambiguous durations by default
authorMatthew Wild <mwild1@gmail.com>
Thu, 30 Nov 2023 13:42:44 +0000
changeset 13371 82513890a1d8
parent 13370 9f1f1e7afdbd
child 13372 80a1ce9974e5
util.human.io: Don't accept ambiguous durations by default The new method parse_duration_lax() exports the old behaviour, mainly for compatibility purposes.
spec/util_human_io_spec.lua
util/human/io.lua
--- a/spec/util_human_io_spec.lua	Thu Nov 30 12:41:26 2023 +0000
+++ b/spec/util_human_io_spec.lua	Thu Nov 30 13:42:44 2023 +0000
@@ -47,6 +47,37 @@
 		local function test(expected, duration)
 			return assert.equal(expected, human_io.parse_duration(duration), ("%q -> %d"):format(duration, expected));
 		end
+		local function should_fail(duration)
+			assert.is_nil(human_io.parse_duration(duration), "invalid duration should fail: %q");
+		end
+		it("works", function ()
+			test(1, "1s");
+			test(60, "1min");
+			test(60, "1 min");
+			test(60, "1 minute");
+			test(120, "2min");
+			test(7200, "2h");
+			test(7200, "2 hours");
+			test(86400, "1d");
+			test(604800, "1w");
+			test(604800, "1week");
+			test(1814400, "3 weeks");
+			test(2678400, "1month");
+			test(2678400, "1 month");
+			test(31536000, "365 days");
+			test(31556952, "1 year");
+
+			should_fail("two weeks");
+			should_fail("1m");
+			should_fail("1mi");
+			should_fail("1mo");
+		end);
+	end);
+
+	describe("parse_duration_lax", function ()
+		local function test(expected, duration)
+			return assert.equal(expected, human_io.parse_duration_lax(duration), ("%q -> %d"):format(duration, expected));
+		end
 		it("works", function ()
 			test(1, "1s");
 			test(60, "1mi");
@@ -66,7 +97,7 @@
 			test(2678400, "1 month");
 			test(31536000, "365 days");
 			test(31556952, "1 year");
-			return assert.is_nil(human_io.parse_duration("two weeks"), "\"2 weeks\" -> nil");
+			return assert.is_nil(human_io.parse_duration_lax("two weeks"), "\"2 weeks\" -> nil");
 		end);
 	end);
 end);
--- a/util/human/io.lua	Thu Nov 30 12:41:26 2023 +0000
+++ b/util/human/io.lua	Thu Nov 30 13:42:44 2023 +0000
@@ -200,13 +200,26 @@
 
 local day = 86400;
 local multipliers = {
-	d = day, w = day * 7, m = 31 * day, mo = 31 * day, y = 365.2425 * day;
-	s = 1, mi = 60, h = 3600, ho = 3600
+	d = day, w = day * 7, mon = 31 * day, y = 365.2425 * day;
+	s = 1, min = 60, h = 3600, ho = 3600
 };
+
 local function parse_duration(duration_string)
+	local n, m = duration_string:lower():match("(%d+)%s*([smhdwy]?[io]?n?)");
+	if not n or not multipliers[m] then return nil; end
+	return tonumber(n) * ( multipliers[m] or 1 );
+end
+
+local multipliers_lax = setmetatable({
+	m = multipliers.mon;
+	mo = multipliers.mon;
+	mi = multipliers.min;
+}, { __index = multipliers });
+
+local function parse_duration_lax(duration_string)
 	local n, m = duration_string:lower():match("(%d+)%s*([smhdwy]?[io]?)");
 	if not n then return nil; end
-	return tonumber(n) * ( multipliers[m] or 1 );
+	return tonumber(n) * ( multipliers_lax[m] or 1 );
 end
 
 return {
@@ -223,4 +236,5 @@
 	ellipsis = ellipsis;
 	table = new_table;
 	parse_duration = parse_duration;
+	parse_duration_lax = parse_duration_lax;
 };