Module:Sandbox/Takidelfin/Dates Explained

-- Task 7 for Google Code-in | Date formatting)testList = possiblePatterns =

local allowedFormats =

-- First object in the array is prefix, second is a suffxlocal circa = local eraSuffix =

local monthsDays = local monthsNames = -- local months =

local p =

isLeapYear = function (yearRaw) year = tonumber(yearRaw) return (((year % 4

0) and (year % 100 ~= 0)) or (year % 400

0))end

extractData = function (dateRaw) msg = "" matched = false -- print ('-- ' .. dateRaw .. ' --') for key, value in pairs(possiblePatterns) do if matched ~= true then local date = date.circa = false --

local match = match.match1, match.match2, match.match3 = dateRaw:match(value.pattern)

for ci, ciValue in pairs(circa) do for cmi,cmiValue in pairs(ciValue) do if ci

1 then local patternDropped = value.pattern:gsub("%)", ""):gsub("%(", "") local patternFinal = "(" .. cmiValue .. ") " .. patternDropped local circaPossibleMatch = dateRaw:match(patternFinal) -- print(patternFinal) if circaPossibleMatch ~= nil then if string.lower(circaPossibleMatch)

string.lower(cmiValue) then date.circa = true end end else local patternDropped = value.pattern:gsub("%)", ""):gsub("%(", "") local patternFinal = patternDropped .. " (" .. cmiValue .. ")" local circaPossibleMatch = dateRaw:match(patternFinal) if circaPossibleMatch ~= nil then if string.lower(circaPossibleMatch)

string.lower(cmiValue:gsub("%%%(", "("):gsub("%%%)", ")")) then date.circa = true end end end end -- match.circa = dateRaw:match("%d+ (AB)") end

for ei=1,2 do -- suffix or preffix local era = eraSuffix[ei] for emi, emiPattern in pairs(eraSuffix[ei]) do local patternDropped = value.pattern:gsub("%)", ""):gsub("%(", "") local patternFinal = patternDropped .. " (" .. emiPattern .. ")" local circaPossibleMatch = dateRaw:match(patternFinal) if circaPossibleMatch ~= nil then if string.lower(circaPossibleMatch)

string.lower(emiPattern) then date.era = emiPattern end end end end -- Each value.pattern (pattern) has got an value.format (date format) associated with it -- this loops iterates thorough them and assings variables to proper value.formats

for i=1,string.len(value.format) + 1 do date[string.sub(value.format, i, i)] = match["match" .. i] end

if tonumber(date.y) ~= nil then date.y = tonumber(date.y) matched = true end

if date.m ~= nil and date.m ~= "" then matched = false local month = if tonumber(date.m) ~= nil then if (tonumber(date.m) or 13) <= 12 then month.name = monthsNames[tonumber(date.m)] month.length = monthsDays[tonumber(date.m)] month.id = tonumber(date.m) matched = true else if value.format

'mdy' then -- print('INVALID ENTRY\n\n') return "Invalid entry" end end elseif #date.m > 1 then for mi=1,#monthsNames do local monthPrefixPossible = string.upper(string.sub(monthsNames[mi], 1, 3)) local monthPrefix = string.upper(string.sub(date.m, 1, 3)) if monthPrefix

monthPrefixPossible then -- print(monthPrefix, monthPrefixPossible) month.name = monthsNames[mi] month.length = monthsDays[mi] month.id = mi matched = true end end else date.m = nil end

if month.name ~= nil and month.length ~= nil then matched = true date.m = month if date.d ~= nil and date.d ~= "" then matched = false date.d = tonumber(date.d) if date.m.length

29 and date.y ~= nil then if isLeapYear(date.y)

true and date.d <= 29 then matched = true else -- print('INVALID ENTRY\n\n') matched = true return "Invalid entry" end elseif not (date.d <= month.length) then date.d = nil else matched = true end end end end if matched

true then -- local dateMsg = "" -- if date.y then -- dateMsg = dateMsg .. date.y -- end -- if date.m then -- dateMsg = dateMsg .. " " .. date.m.name -- end -- if date.d then -- dateMsg = dateMsg .. " " .. date.d -- end -- if date.circa then -- dateMsg = "circa " .. dateMsg -- end -- if date.era then -- dateMsg = dateMsg .. " " .. date.era -- end -- print('FORMAT: ' .. value.format) -- print('PATTERN: ' .. value.pattern) -- print('CIRCA: ' .. tostring(date.circa)) -- print('ERA: ' .. tostring(date.era)) -- print('--- Result ---') -- print(dateMsg) -- print('\n\n') return date end end endend

formatDate = function (date, formatRaw) if (date

nil) or (date

'Invalid entry') then return 'Invalid entry' elseif formatRaw ~= nil then local format = allowedFormats[formatRaw] or 'invalidFormat' if format

'invalidFormat' then local returnValue = "" if date.d then returnValue = returnValue .. date.d .. " " end if date.m then returnValue = returnValue .. date.m.name .. " " end if date.y then returnValue = returnValue .. date.y .. " " end if date.circa then returnValue = "circa " .. returnValue end if date.era then returnValue = returnValue .. date.era .. " " end return returnValue end

local finalFormat = format local formatIterator = format:gsub("%$", "") for l=1,#formatIterator do local char = formatIterator:sub(l,l) -- Day if char

"d" then if date.d

nil then if formatRaw

"iso" then return "Invalid entry" end finalFormat = finalFormat:gsub("%$d%$", "") elseif #tostring(date.d) < 2 then finalFormat = finalFormat:gsub("%$d%$", 0 .. date.d) else finalFormat = finalFormat:gsub("%$d%$", date.d) end elseif char

"D" then if date.d

nil then if formatRaw

"iso" then return "Invalid entry" end finalFormat = finalFormat:gsub("%$D%$", "") else finalFormat = finalFormat:gsub("%$D%$", date.d) end end -- Year if char

"y" then if date.y

nil then finalFormat = finalFormat:gsub("%$y%$", "") else finalFormat = finalFormat:gsub("%$y%$", date.y) end elseif char

"Y" then if date.y

nil then if formatRaw

"iso" then return "Invalid entry" end finalFormat = finalFormat:gsub("%$Y%$", "") elseif 0 <= date.y and date.y <= 9999 then local zero = "0" finalFormat = finalFormat:gsub("%$Y%$", zero:rep(4 - #tostring(date.y)) .. date.y) else return "Invalid entry" end end -- Era if char

"E" then if date.era

nil then if formatRaw

"iso" then return "Invalid entry" end finalFormat = finalFormat:gsub("%$E%$", "") else finalFormat = finalFormat:gsub("%$E%$", date.era) end end -- Month if char

"m" then if date.m

nil then if formatRaw

"iso" then return "Invalid entry" end finalFormat = finalFormat:gsub("%$m%$", "") else local zero = "0" finalFormat = finalFormat:gsub("%$m%$", zero:rep(2 - #tostring(date.m.id)) .. date.m.id) end elseif char

"M" then if date.m

nil then if formatRaw

"iso" then return "Invalid entry" end finalFormat = finalFormat:gsub("%$M%$", "") else finalFormat = finalFormat:gsub("%$M%$", date.m.name) end end end -- Circa if date.circa then if formatRaw

"iso" then return "ISO format does not allow uncertain dates" end finalFormat = "circa " .. finalFormat end

if date.era and formatRaw

"iso" then return "ISO format does not allow embedding era into date" end

finalFormat = finalFormat:gsub("^%s*(.-)%s*$", "%1") finalFormat = finalFormat:gsub("%s+", " ") return finalFormat else local returnValue = "" if date.d then returnValue = returnValue .. date.d .. " " end if date.m then returnValue = returnValue .. date.m.name .. " " end if date.y then returnValue = returnValue .. date.y .. " " end if date.circa then returnValue = "circa " .. returnValue end if date.era then returnValue = returnValue .. date.era .. " " end return returnValue endend

p.convertTest = function (frame) local msg = "" for i=1, #testList do local testDate = testList[i] msg = msg .. "

" end return msgend

p.convertDate = function (frame) local date = frame.args.date local format = frame.args.format if date

nil or date

"" then return "Invalid entry" end return formatDate(extractData(date), format)end

return p