Module:Sandbox/Ajuanca/Dates Explained

-- Task 9 of GCI 2019local p =

-- Main functionfunction p.formatDates(frame) local inputDate = tostring(frame.args.name) local inputFormat=tostring(frame.args.format) local inputTable = p.divideString(inputDate) local str="" local myDate = p.getDate(inputTable) local dateResults = p.checkDate(myDate) if(not(dateResults.isDateCorrect))then return dateResults.errorMessage else local outputFormat=p.chooseFormat(myDate, inputFormat) local completeMonths= if(myDate.isAprox)then str="circa " end if(outputFormat

"dmy")then str = str .. myDate.day .. " " .. completeMonths[myDate.month] .. " " .. myDate.year elseif(outputFormat

"mdy")then str = str .. completeMonths[myDate.month] .. " " .. myDate.day .. ", " .. myDate.year elseif(outputFormat

"iso")then str = str .. myDate.year .. "-" .. myDate.month .. "-" .. myDate.day elseif(outputFormat

"y")then str=str..myDate.year elseif(outputFormat

"my")then str=str.. completeMonths[myDate.month] .. " " .. myDate.year end if(myDate.specifiedEra~= nil)then str = str .." "..myDate.specifiedEra end end return strend

-- Selects correct output format.-- Returns a Stringfunction p.chooseFormat(dateObject, prefference) local correctFormat="" if(dateObject.dateFormat~= nil)then correctFormat=dateObject.dateFormat else correctFormat="#error" end local compatibleFormats = for n, actualFormat in ipairs(compatibleFormats) do if (prefference:lower

actualFormat) then correctFormat=prefference:lower break end end return correctFormatend

-- Truncates the input by spaces.-- Returns a tablefunction p.divideString(stringSentence) local nameTable = stringSentence = string.gsub(stringSentence, "-", " ") stringSentence = string.gsub(stringSentence, "/", " ") for m in string.gmatch(stringSentence, ("%S+")) do table.insert(nameTable, m) end return nameTableend

-- Detects input date.-- Returns a Objectfunction p.getDate(stringTable) local comparison = "" local finalDate = local dateIsStored = false -- Matchs string month with correspoding number. -- Returns number function getMonth(strInput) local months = if(strInput:find("(%a+)"))then for w, month in ipairs(months)do if(strInput:lower:find(month)~= nil)then return tonumber(w) end end end return 0 end -- Match given ordinal number to its cardinal value. -- Returns a number function getCardinal(inputStr) if(inputStr:find("(%d+)(%a+)"))then local number, termination=inputStr:lower:match("(%d+)(%a+)") suffixes = for g, suffix in ipairs(suffixes)do if(termination:find(suffix))then return tonumber(number) end end end return 0 end -- Start comparison for z, number in ipairs(stringTable) do -- Creates a string of three followed items. if(z<=#stringTable-2)then local comparison = stringTable[z] .. " " .. stringTable[z+1] .. " " .. stringTable[z+2] -- Search for the format 'typedMonth Day, Year'. if(comparison:lower:find("(%a+) (%d+), (%d+)"))then local m, d, y = comparison:lower:match("(%a+) (%d+), (%d+)") finalDate.month=tonumber(getMonth(m)) finalDate.year=tonumber(y) finalDate.day=tonumber(d) finalDate.dateFormat="mdy" dateIsStored=true end -- Search for the format 'Day typedMonth Year' if(comparison:lower:find("(%d+) (%a+) (%d+)") and not(dateIsStored))then local d, m, y = comparison:lower:match("(%d+) (%a+) (%d+)") finalDate.month=getMonth(m:lower) finalDate.year=tonumber(y) finalDate.day=tonumber(d) finalDate.dateFormat="dmy" if(finalDate.month

0)then dateIsStored=false else dateIsStored=true end end -- Search for the format 'Day Month Year' or 'Year Month Day' if(comparison:lower:find("(%d+) (%d+) (%d+)") and not(dateIsStored))then local d, m, y= comparison:lower:match("(%d+) (%d+) (%d+)") -- If day and year are both less than 31, it'll be considered d-m-y if(tonumber(d)>31)then local temporalDay=y y=d d=temporalDay end finalDate.month=tonumber(m) finalDate.year=tonumber(y) finalDate.day=tonumber(d) -- This format isn't allowed. The most similar is ISO. finalDate.dateFormat="iso" if(finalDate.month

0)then dateIsStored=false else dateIsStored=true end end -- Search for format 'ordinalDay typedMonth Year' if(comparison:lower:find("(%w+) (%a+) (%d+)") and not(dateIsStored))then local d, m, y=comparison:lower:match("(%w+) (%a+) (%d+)") finalDate.day=getCardinal(d) finalDate.month=getMonth(m) finalDate.year=y -- This format isn't allowed. The most similar is ISO. finalDate.dateFormat="iso" if(finalDate.month

0)then dateIsStored=false else dateIsStored=true end end end -- Searchs for aproximations indicators local aproxIndicators = for z, indicator in ipairs(aproxIndicators)do if(number:lower:match(indicator))then finalDate.isAprox=true end end -- Searchs for era indicators. Note that, althought it isn't used, -- the value g gives us the calendar used. local eraIndicators= for d, era in ipairs(eraIndicators)do for g, specific in ipairs(era)do if(specific

number:lower)then finalDate.specifiedEra=specific:upper end end end end if(not(dateIsStored))then for k, number in ipairs(stringTable) do -- Creates a string of two followed elements. if(k<=#stringTable-1)then local comparison = stringTable[k] .. " " .. stringTable[k+1] -- Search for a date in format 'Day typedMonth' if(comparison:lower:find("(%d+) (%a+)"))then local d, m=comparison:lower:match("(%d+) (%a+)") finalDate.day=tonumber(d) finalDate.month=tonumber(getMonth(m)) -- This format isn't allowed. The most similar is ISO. finalDate.dateFormat="iso" if(finalDate.month

0)then dateIsStored=false else dateIsStored=true end -- Search for a date in format 'ordinalDay typedMonth' elseif(comparison:lower:find("(%w+) (%a+)"))then local d, m=comparison:lower:match("(%w+) (%a+)") finalDate.day=getCardinal(d) finalDate.month=getMonth(m) -- This format isn't allowed. The most similar is ISO. finalDate.dateFormat="iso" if(finalDate.day

0)then dateIsStored=false else dateIsStored=true end end -- Search for a date in format 'typedMonth Year' if(comparison:lower:find("(%a+) (%d+)"))then local m, y=comparison:lower:match("(%a+) (%d+)") finalDate.month=getMonth(m) finalDate.year=tonumber(y) finalDate.dateFormat="my" if(finalDate.month

0)then dateIsStored=false else dateIsStored=true end end end end end -- Search for a result if nothing is still found. if(not(dateIsStored))then local numbersFound = for n, number in ipairs(stringTable)do -- Search for possible given values in an non-regulated order. if(number:find("(%a+)")~=nil)then if(finalDate.day

0 and number:find("(%d+)"))then -- Search for ordinal day finalDate.day=getCardinal(number) if(not(finalDate.day

0))then finalDate.dateFormat="dmy" end elseif(finalDate.month

0)then -- Search for months finalDate.month=tonumber(getMonth(number)) if(not(finalDate.month

0))then finalDate.dateFormat="my" end end else table.insert(numbersFound, tonumber(number)) end if(#numbersFound

1 and #stringTable

n)then finalDate.year=numbersFound[1] if((finalDate.month~=0) and (finalDate.day~=0))then finalDate.dateFormat="dmy" elseif(finalDate.month~=0)then finalDate.dateFormat="my" else finalDate.dateFormat="y" end elseif(#numbersFound

2 and #stringTable

n)then if(numbersFound[1]<=31) then finalDate.day=numbersFound[1] finalDate.year=numbersFound[2] else finalDate.year=numberFound[1] finalDate.day=numberFound[2] end finalDate.dateFormat="y" end end end return finalDateend

-- Checks that given date-- Returns a objectfunction p.checkDate(givenDate) -- Detects is the given year is leap. -- Returns a boolean function isLeap(yearInput) local yearIsLeap = (tonumber(yearInput)%4)

0 if((tonumber(yearInput)%100)

0)then yearIsLeap = (tonumber(yearInput)%400)

0 end return yearIsLeap end local finalObject = -- Check if day is correct if(not(givenDate.day

nil))then if(givenDate.day>31)then finalObject.isDateCorrect=false finalObject.errorMessage="That day doesn't exists!" return finalObject end end if(not(givenDate.month

nil))then if(givenDate.month

2)then if(isLeap(givenDate.year))then if(givenDate.day>29)then finalObject.isDateCorrect=false finalObject.errorMessage="That day doesn't exists!" end else if(givenDate.day>=29)then finalObject.isDateCorrect=false finalObject.errorMessage="That day doesn't exists!" end end end end -- Check if month is correct if(not(givenDate.month

nil))then if(givenDate.month>12)then finalObject.isDateCorrect=false finalObject.errorMessage="That month doesn't exist!" end end -- Check if date is nil if(givenDate.year

0 and givenDate.day

0 and givenDate.month

0)then finalObject.isDateCorrect=false finalObject.errorMessage="No date was detected." end return finalObjectendreturn p