Module:Countdown Message

--Module:Pi day

local p = {} ---BUILD FUNCTION--- function p.Main(frame) --Import Arguments --This call is necessary to read in data from the page data = frame:getParent.args; --current date values for the math (fetch from system) c_year = os.date("%Y"); c_month = os.date("%m"); c_day = os.date("%d"); --target date values for the math t_year = pfetch("target_year"); if (t_year == "") then return "Invalid Year given." elseif (t_year) then t_year = formatnum(t_year) end --Nil is a valid state, check later. t_month = pfetch("target_month"); if (not t_month or t_month == "") then return "target_month missing" else t_month = formatnum(t_month) end t_day = pfetch("target_day"); if (not t_day or t_day == "") then return "target_day missing" else t_day = formatnum(t_day) end --Input verification: preventing out of bounds entries if t_month < 1 or t_month > 12 then return "invalid month"; end if t_day < 1 or t_day > 31 then return "invalid day"; end --load messages. prefix = pfetch("counter_prefix") if not prefix then prefix = "" else prefix = prefix .. " " end suffix = pfetch("counter_suffix"); if not suffix then suffix = "" else suffix = " " .. suffix end msg = pfetch("target_message"); if not msg then msg = "" end --[[Math Explantion. By treating every month as if it has 31+ days and adding the current day of the month, every day of the year is given unique value. Comparing these values allows the program to identify whether the current date is before, on, or after the given day of the year, and select an output accordingly. Non-Reset mode math: B treating the year as having 365+ days, and applying the same math as the month, every day in history can be given a unique value. Comparing these values works exactly the same as without a year.

If the year is defined, count up to the target, then display the target message. If the year is not defined, count to the target day, display the target message on that day, and reset the next day by indexing the year. ]]

if (t_year) then --Check for Non-Reset mode --generate date ID's		c_ID = c_year * 400 + c_month * 32 + c_day; t_ID = t_year * 400 + t_month * 32 + t_day; if t_ID > c_ID then --before the target day, return countdown return prefix .. "" .. Month_Name(t_month) .. " " .. t_day .. " " .. c_year .. " 00:00:00 " .. suffix; else --Everything else should return the Target Message return msg; end else --Reset Mode --generate date ID's		c_ID = c_month * 32 + c_day; t_ID = t_month * 32 + t_day; if t_ID > c_ID then --before the target day, return countdown return prefix .. "" .. Month_Name(t_month) .. " " .. t_day .. " " .. c_year .. " 00:00:00 " .. suffix; elseif t_ID == c_ID then --Return a special message on the target day. return msg; elseif t_ID < c_ID then --after the target day, return next year's countdown return prefix .. "" .. Month_Name(t_month) .. " " .. t_day .. " " .. (c_year+1) .. " 00:00:00 " .. suffix; end end --final error message for safety. return "CRITICAL SYSTEM ERROR."; end

--Month name fetch function function Month_Name(month) if month == 1 then return "January"; elseif month == 2 then return "February"; elseif month == 3 then return "March"; elseif month == 4 then return "April"; elseif month == 5 then return "May"; elseif month == 6 then return "June"; elseif month == 7 then return "July"; elseif month == 8 then return "August"; elseif month == 9 then return "September"; elseif month == 10 then return "October"; elseif month == 11 then return "November"; elseif month == 12 then return "December"; end return nil; --This is an error state. end

--Function for converting strings to numbers function formatnum(str) return tonumber(string.gsub(str,",",""),10); end

--Protected fetch function-reads in data and returns errors as false function pfetch(target) local temp; --temporary variable if (select(1,pcall(function temp=data[target]; end))) then --attempt fetch, use pcall to catch any errors, and return the requested data on success. return temp; else --if read attempt failed, return nil. return nil; end end

return p;