---@class CronJob ---@field h number ---@field m number ---@field cb function ---@type CronJob[] local Jobs = {} ---@type number|false local LastTime = false ---@param h number ---@param m number ---@param cb function function RunAt(h, m, cb) Jobs[#Jobs + 1] = { h = h, m = m, cb = cb, } end ---@return number function GetUnixTimestamp() return os.time() end ---@param time number function OnTime(time) for i = 1, #Jobs, 1 do local scheduledTimestamp = os.time({ hour = Jobs[i].h, min = Jobs[i].m, sec = 0, -- Assuming tasks run at the start of the minute day = os.date("%d", time), month = os.date("%m", time), year = os.date("%Y", time), }) if time >= scheduledTimestamp and (not LastTime or LastTime < scheduledTimestamp) then local d = os.date('*t', scheduledTimestamp).wday Jobs[i].cb(d, Jobs[i].h, Jobs[i].m) end end end ---@return nil function Tick() local time = GetUnixTimestamp() if not LastTime or os.date("%M", time) ~= os.date("%M", LastTime) then OnTime(time) LastTime = time end SetTimeout(60000, Tick) end LastTime = GetUnixTimestamp() Tick() AddEventHandler("cron:runAt", function(h, m, cb) assert(type(h) == "number", ("Expected number for h, got %s"):format(type(h))) assert(type(m) == "number", ("Expected number for m, got %s"):format(type(m))) assert(type(cb) == "function", ("Expected function for cb, got %s"):format(type(cb))) RunAt(h, m, cb) end)