Module:Sandbox/Deimos18/Dates
Appearance
-- Deimos Google Code-in, Date formatting
-- Plan of action:
-- Find type of string
-- Separate out day, month and year
-- Format date according to desired format
-- Add exceptions for February
-- Find and remove useless words which taint the text to find the required date
-- Find special words like "uncertain" and "around" to replace with "circa"
local p = {}
months = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"} -- for iso-type dates
month_s = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"} -- for 3-lettered month dates (it won't get shorter than this, would it?)
circa = {"around", "sometime around", "uncertain", "approximately", "approx", "about", "probably", "circa"}
eralist = {"CE", "BC", "BCE", "AD"}
function flUpper (str)
local str = str or ""
local l_check = string.match(str, "(%a+)") -- To take the first letter-y part of the string out of the complete string (for editing, ofc)
local str_fi, str_la = string.find(str, "(%a+)") -- Find the first and last indices of the first letter-y part of string that appears
if (str_fi == nil and l_check == nil) then -- checking if the string even consists letters
out = str -- return back whatever there is since there's no letter anyways
else
local str_bef = string.sub(str,1,(str_fi-1)) -- Obtaining the part of the string before the first letter
local str_fl = string.sub(l_check,1,1) -- Getting the first letter
local str_cap = string.upper(str_fl) -- Capitalizing the first letter
local str_end = string.sub(str, str_fi+1) -- Obtaining the rear part of the string i.e. the part after the first letter
out = str_bef .. str_cap .. str_end -- Joining together the front, capitalized and rear part to return the complete string
end
return out
end
addCirca = ""
function findType (str) -- To check if data type is other than mdy
str = str or ""
dateType = ""
local fts = ""
local fte = ""
fts, fte = string.find(str, "(%d+)-(%d+)-(%d+)")
if (fts ~= nil) then
dateType = "iso"
end
fts, fte = string.find(str, "(%d+)/(%d+)/(%d+)")
if (fts ~= nil) then
dateType = "slashed"
end
for n=1,#circa do
findCirca = string.match(str, circa[n])
if (findCirca ~= nil) then
addCirca = "circa "
break
else
addCirca = ""
end
end
if (dateType == nil) then dateType = "dmy" end
return dateType
end
function isoDates (str)
local yeari, monthnum, dayi = string.match(str, "(%d%d%d%d)-(%d%d)-(%d%d)")
local monthi = flUpper(months[tonumber(monthnum)])
return dayi, monthi, yeari
end
function slashedDates (str)
local days, monthnum, years = string.match(str, "(%d%d)/(%d%d)/(%d%d%d%d)")
local monthsl = flUpper(months[tonumber(monthnum)])
return days, monthsl, years
end
function findEra (str)
str = str or ""
local era = ""
for q=1,#eralist do
era = string.match(str, eralist[q])
if (era ~= nil) then
break
else
era = ""
end
end
return era
end
function findFebruary (day, month, year)
local day = tonumber(day) or ""
local month = month or ""
local year = tonumber(year) or ""
local nofeb = "nofeb"
if (month == "February") then
if ((year%4)==0) then
if (day > 29) then
return false
else
return true
end
else
if (day > 28) then
return false
else
return true
end
end
else
return nofeb
end
end
p.formatDate = function (frame)
local text = string.lower(frame.args.text)
local format = frame.args.format or "dmy"
dtype = findType(text)
invEnt = false
eras = findEra(text) or ""
local out = ""
ms = ""
me = ""
mst = false
local msn = ""
for i=1,#months do
ms, me = string.find(text,months[i])
if (ms ~= nil) then break end
end
if (ms == nil) then
for i=1,#month_s do
ms, me = string.find(text,month_s[i])
if (ms ~= nil) then
msn = i
mst = true
break
end
end
end
if (ms ~= nil) then
if (mst==true) then
month = flUpper(months[msn])
else
month = flUpper(string.sub(text, ms, me))
end
else
month = ""
end
local year = string.match(text, "%d%d%d%d") or ""
if (year == "") then
year = string.match(text, "%d%d%d") or ""
end
local leftOutString = string.gsub(text, year, "none", 1)
if (month == "" and year ~= "") then
day = ""
else
day = string.match(leftOutString, "(%d+)")
end
if (dtype == "iso") then day, month, year = isoDates(text) end
if (dtype == "slashed") then day, month, year = slashedDates(text) end
if (day == nil or day == "") then day = "32" end
out = out .. addCirca .. day .. " " .. month .. " " .. year .. " " .. eras
febCheck = findFebruary(day,month,year)
if (febCheck ~= "nofeb" and febCheck==false) then invEnt = true end
if ((febCheck == "nofeb") and (tonumber(day) > 31)) then invEnt = true end
if (invEnt == true) then out = "Invalid Entry" end
return out
end
return p