Mòideal:Teamplaid:ConvertDate
Documentation for this module may be created at Mòideal:Teamplaid:ConvertDate/doc
-- Converts English dates to ISO dates.
-- If the input is a single month name (e.g. "January"), returns the number for the month as a 2-digit string
-- The following formats have been tested:
-- April
-- April 2016
-- April 1, 2016
-- 1 April 2016
-- 1st April 2016
-- 2nd April 2016
-- ...
-- 5.4.2006
local p = {}
-- Turns 1 digit number strings into 2 digit number strings with leading zero
local function format_number(String)
local Number = tonumber(String)
if (Number < 10) then
return "0" .. Number
else
return String
end
end
-- Seems like here is no built-in is_number function
local function is_number(String)
for c in String:gmatch"." do
if (c~="0" and c~="1" and c~="2" and c~="3" and c~="4" and c~="5" and c~="6" and c~="7" and c~="8" and c~="9") then
return false
end
end
return true
end
-- Returns whether a number is too big to be a day
local function is_year(String)
return is_number(String) and tonumber(String) > 31
end
-- Returns whether a number is too big to be a month
local function not_month_number(String)
return is_number(String) and tonumber(String) > 12
end
-- Returns whether a number can be a be a day
local function in_day_range(String)
return is_number(String) and tonumber(String) >= 1 and tonumber(String) <= 31
end
-- Returns whether a number can be a be a month
local function in_month_range(String)
return is_number(String) and tonumber(String) >= 1 and tonumber(String) <= 12
end
-- Checks for suffixes like "st", "nd", "," ...
-- Reurns nil if this isn't a number followed by one of those suffixes.
-- Otherwise, strips away the suffix and returns the number as a 2-digit string
local function day_from_day_with_suffix(String)
local Suffix = string.sub(String, -1)
if (Suffix == ",") then
local DayString = string.sub(String, 1, string.len(String)-1)
if (in_day_range(DayString)) then
return DayString
end
end
Suffix = string.sub(String, -2)
if (Suffix == "st" or Suffix == "nd" or Suffix == "rd" or Suffix == "th") then
local DayString = string.sub(String, 1, string.len(String)-2)
if (in_day_range(DayString)) then
return DayString
end
end
return nil
end
-- Checks if the inpur has been successfully parsed
local function check_result(Date, Year, Month, Day)
if (Date[2] == nil) then
return tonumber(Year) > 0
elseif (Date[3] == nil) then
return tonumber(Year) > 0 and in_month_range(Month)
else
return tonumber(Year) > 0 and in_month_range(Month) and in_day_range(Day)
end
end
local function Run(Args)
-- Check for number of arguments
if (Args[1] ==nil) then
return '<span class="error">[[Teamplaid:ConvertDate]]: Feumaidh tu 1 argamaid a shònrachadh ach cha robh gin ann!</span>'
end
if (Args[2] ~=nil) then
return '<span class="error">[[Teamplaid:ConvertDate]]: Na sònraich barrachd air 1 argamaid!</span>'
end
local Arg = mw.ustring.lower(mw.text.trim(Args[1] or ""));
if (Arg == "") then
return '<span class="error">[[Teamplaid:ConvertDate]]: Tha an argamaid falamh!</span>'
end
-- Output variables
local Year = "0000"
local Month = "00"
local Day = "00"
-- Track already parsed elements
local YearIndex = 0
local MonthIndex = 0
local DayIndex = 0
-- Months table
local Months = {}
Months["january"] = "01"
Months["jan"] = "01"
Months["jan."] = "01"
Months["february"] = "02"
Months["feb"] = "02"
Months["feb."] = "02"
Months["march"] = "03"
Months["mar"] = "03"
Months["mar."] = "03"
Months["april"] = "04"
Months["apr"] = "04"
Months["apr."] = "04"
Months["may"] = "05"
Months["june"] = "06"
Months["jun"] = "06"
Months["jun."] = "06"
Months["july"] = "07"
Months["jul"] = "07"
Months["jul."] = "07"
Months["august"] = "08"
Months["aug"] = "08"
Months["aug."] = "08"
Months["september"] = "09"
Months["sep"] = "09"
Months["sep."] = "09"
Months["october"] = "10"
Months["oct"] = "10"
Months["oct."] = "10"
Months["november"] = "11"
Months["nov"] = "11"
Months["nov."] = "11"
Months["december"] = "12"
Months["dec"] = "12"
Months["dec."] = "12"
-- If we only have a month, we're done.
if (Months[Arg] ~= nil) then
return Months[Arg]
end
-- Tokenize the string
local Date={}
for i in string.gmatch(Arg, "%S+") do
table.insert(Date, i)
end
-- Maybe something other than whitespace has been used as a delimiter?
if (Date[2] == nil) then
Date = {}
for i in string.gmatch(Arg, "[^.]+") do
table.insert(Date, mw.text.trim(i))
end
if (Date[1]~=nil and Date[2]~=nil and Date[3]~=nil) then
-- Output
if (not check_result(Date, Date[3], Date[2], Date[1])) then
return Args[1] -- Conversion failed
else
return Date[3] .. "-" .. format_number(Date[2]) .. "-" .. format_number(Date[1])
end
end
end
-- Detect string elements as day, month or year
local Unparsed={}
for i, v in ipairs(Date) do
local TempDay = day_from_day_with_suffix(v)
if (TempDay ~= nil) then
Day = TempDay
DayIndex = i
elseif (Months[v] ~= nil) then
Month = Months[v]
MonthIndex = i
elseif (is_year(v)) then
Year = v
YearIndex = i
elseif (not_month_number(v)) then
Day = v
DayIndex = i
else
table.insert(Unparsed, v)
end
end
-- Pick up the stragglers
for i, v in ipairs(Unparsed) do
if (is_number(v)) then
if (MonthIndex > 0 and YearIndex > 0) then
Day = v
DayIndex = i
elseif (DayIndex > 0 and YearIndex > 0) then
Month = v
MonthIndex = i
elseif (DayIndex > 0 and MonthIndex > 0) then
Year = v
YearIndex = i
end
end
end
-- Output
if (not check_result(Date, Year, Month, Day)) then
return Args[1] -- Conversion failed
else
return Year .. "-" .. format_number(Month) .. "-" .. format_number(Day)
end
end
function p.Execute(frame)
return Run(frame:getParent().args)
end
return p