Module:Sandbox/Stibba0/Dates

local months = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }

local allowedFormats = { ["dmy"]="(%d+) (%a+) (%d+)", ["mdy"]="(%a+) (%d+), (%d+)", ["ds"]="(%d+)%a%a (%a+) (%d+)", ["iso"]="(%d+)-(%d+)-(%d+)", ["isoSlash"]="(%d+)/(%d+)/(%d+)", ["my"]="(%a+) (%d+)", ["dd"]="(%d+)%a%a", ["year"]="(%d+)", }

local formatNames = { [1]="dmy", [2]="mdy", [3]="iso", [4]="isoSlash", [5]="ds", [6]="dd", [7]="my", [8]="year" }

local christ = { "BCE", "AD", "BC", "CE" }

local circa = { "circa", "around", "uncertain", "sometime" }

local p = {}

local glueString = function(one, two, three, between) return one .. between .. two .. between .. three end

local identifyDate = function(dateString) local day, month, year, frmt = nil for index, val in ipairs(months) do		-- Checks for months in the string through the first 3 chars of each month if string.match(string.lower(dateString), string.lower(string.sub(months[index], 1, 3))) then month = val end end for _, val in ipairs(formatNames) do -- If there is a pattern in the text it gets whatever data belongs to that. if string.match(dateString, allowedFormats[val]) then datePart = string.sub(dateString, string.find(dateString, allowedFormats[val])) if string.match(datePart, "%a+") and not (month == nil) then if val == "ds" then frmt = "dmy" datePart = string.gsub(datePart,"%a%a", "", 1 ) end if val == "my" then frmt = "my" year = string.match(datePart, "%d+") elseif val == "dd" then frmt = "dmy" day = string.match(datePart, "%d+") datePart = string.gsub(dateString, allowedFormats[val], "") year = string.match(datePart, "%d+") else if val == "dmy" then frmt = "dmy" else frmt = "mdy" end day = string.match(datePart, "%d+") local _, last = string.find(datePart, "%d+") year = string.match(datePart, "%d+", last+1) end return { ["day"]=day, ["month"]=month, ["year"]=year, ["frmt"]=frmt } else if string.match(dateString, "(%d+) (%a+)") and not (month == nil) then frmt = "plain" day = string.match(dateString, "(%d+) %a+") elseif val == "year" then if string.match(dateString, "%a+") and (not string.match(dateString, "year")) then for i=1, #circa do							if string.match(dateString, circa[i]) or string.match(dateString, christ[i]) then year = string.match(datePart, "%d+") frmt = "year" break end end else frmt = "year" year = string.match(datePart, "%d+") if string.match(dateString, "(%d+) (%d+)") then if tonumber(year) < tonumber(string.match(dateString, "%d+ (%d+)")) then year = string.match(dateString, "%d+ (%d+)") end end end elseif val == "iso" then frmt = "iso" year, monthNum, day = string.match(datePart, allowedFormats[val]) month = months[tonumber(monthNum)] elseif val == "isoSlash" then frmt = "iso" day, monthNum, year = string.match(datePart, allowedFormats[val]) month = months[tonumber(monthNum)] end if not (year == nil) then return { ["day"]=day, ["month"]=month, ["year"]=year, ["frmt"]=frmt } end end end end return { ["day"]=day, ["month"]=month, ["year"]=year, ["frmt"]=frmt } end

local transformDate = function(text, dateData, dateFormat) if ((dateData["day"] == nil) and (dateData["month"] == nil) and (dateData["year"] == nil)) or dateData == nil then return "Invalid entry" end if dateFormat == "" then dateFormat = dateData["frmt"] end local returnString = "" if (not (dateData["day"] == nil)) and (not (dateData["month"] == nil)) and (not (dateData["year"] == nil)) then if tonumber(dateData["day"]) < 10 then dateData["day"] = "0" .. dateData["day"] end if dateFormat == "dmy" then returnString = glueString(dateData["day"], dateData["month"], dateData["year"], " ") elseif dateFormat == "mdy" then returnString = dateData["month"] .. " " .. dateData["day"] .. ", " .. dateData["year"] elseif dateFormat == "iso" then local month = 0 for index, value in ipairs(months) do		       if value == dateData["month"] then month = index end end local monthString = tostring(month) if month < 10 then monthString = "0" .. monthString end returnString = glueString(dateData["year"], monthString, dateData["day"], "-") end end if (not (dateData["month"] == nil)) and (not (dateData["year"] == nil)) and (dateFormat == "my") then returnString = glueString(dateData["month"], dateData["year"], "", " ") end if (dateFormat == "year") and (not (dateData["year"] == nil)) then returnString = dateData["year"] end if dateFormat == "plain" then returnString = glueString(dateData["day"], dateData["month"], "", " ") end if returnString == "" then return "Invalid entry" end for _, val in ipairs(circa) do		if string.match(text, val) then returnString = "circa " .. returnString break end end for _, val in ipairs(christ) do		if string.match(text, val) then returnString = glueString(returnString, val, "", " ") break end end return returnString end

p.getDate = function(frame) local text = frame.args.date local format = frame.args.format or "" -- identifyDate gets the day, month, year and standard format of the text local dateData = identifyDate(text) -- transformDate transforms to the right type of date local dateString = transformDate(text, dateData, string.lower(format))

return dateString end

return p