feat(parse): add parse_duration_to_days for duration string conversion

Problem: The archive command accepted only a bare integer for days,
inconsistent with the `+Nd`/`+Nw`/`+Nm` duration syntax used elsewhere.

Solution: Add `parse_duration_to_days()` supporting `Nd`, `Nw`, `Nm`,
and bare integers. Returns nil on invalid input for caller error handling.
This commit is contained in:
Barrett Ruth 2026-03-08 20:25:22 -04:00
parent c5d55e5e92
commit 8cfdafe464
2 changed files with 67 additions and 0 deletions

View file

@ -667,4 +667,29 @@ function M.is_today(due)
return time_part >= current_time
end
---@param s? string
---@return integer?
function M.parse_duration_to_days(s)
if s == nil or s == '' then
return nil
end
local n = s:match('^(%d+)d$')
if n then
return tonumber(n) --[[@as integer]]
end
n = s:match('^(%d+)w$')
if n then
return tonumber(n) --[[@as integer]] * 7
end
n = s:match('^(%d+)m$')
if n then
return tonumber(n) --[[@as integer]] * 30
end
n = s:match('^(%d+)$')
if n then
return tonumber(n) --[[@as integer]]
end
return nil
end
return M

View file

@ -416,6 +416,48 @@ describe('parse', function()
end)
end)
describe('parse_duration_to_days', function()
it('parses days suffix', function()
assert.are.equal(7, parse.parse_duration_to_days('7d'))
end)
it('parses weeks suffix', function()
assert.are.equal(21, parse.parse_duration_to_days('3w'))
end)
it('parses months suffix (approximated as 30 days)', function()
assert.are.equal(60, parse.parse_duration_to_days('2m'))
end)
it('parses bare integer as days', function()
assert.are.equal(30, parse.parse_duration_to_days('30'))
end)
it('returns nil for nil input', function()
assert.is_nil(parse.parse_duration_to_days(nil))
end)
it('returns nil for empty string', function()
assert.is_nil(parse.parse_duration_to_days(''))
end)
it('returns nil for unrecognized input', function()
assert.is_nil(parse.parse_duration_to_days('xyz'))
end)
it('returns nil for negative numbers', function()
assert.is_nil(parse.parse_duration_to_days('-7d'))
end)
it('handles single digit', function()
assert.are.equal(1, parse.parse_duration_to_days('1d'))
end)
it('handles large numbers', function()
assert.are.equal(365, parse.parse_duration_to_days('365d'))
end)
end)
describe('input_date_formats', function()
before_each(function()
config.reset()