-- Read all "birthday.*" memory keys, find the next upcoming date. local lang = jarvis.context.language local now = jarvis.context.time local entries = {} for _, f in ipairs(jarvis.memory.all() or {}) do if f.key and f.key:sub(1, 9) == "birthday." then local d, m = f.value:match("^(%d?%d)%.(%d?%d)") if d and m then table.insert(entries, { name = f.key:sub(10), day = tonumber(d), month = tonumber(m), }) end end end if #entries == 0 then return jarvis.cmd.not_found(lang == "ru" and "Дней рождения в памяти нет, сэр." or "No birthdays stored, sir.") end -- Compute "days until" for each. Wrap to next year if month/day already passed. local function days_until(e) local today_idx = now.month * 31 + now.day local their_idx = e.month * 31 + e.day local delta = their_idx - today_idx if delta < 0 then delta = delta + 12 * 31 -- approximate "wrap to next year" end return delta end for _, e in ipairs(entries) do e.delta = days_until(e) end table.sort(entries, function(a, b) return a.delta < b.delta end) local nxt = entries[1] local human if nxt.delta == 0 then human = lang == "ru" and "сегодня" or "today" elseif nxt.delta == 1 then human = lang == "ru" and "завтра" or "tomorrow" else human = string.format(lang == "ru" and "через %d дней" or "in %d days", nxt.delta) end return jarvis.cmd.ok(string.format(lang == "ru" and "Ближайший — %s, %s (%02d.%02d)." or "Next: %s, %s (%02d.%02d).", nxt.name, human, nxt.day, nxt.month))