Modül:Infobox date field metadata
local main = {};
local monthIndices = { ['january'] = 1, ['february'] = 2, ['march'] = 3, ['april'] = 4, ['may'] = 5, ['june'] = 6, ['july'] = 7, ['august'] = 8, ['september'] = 9, ['october'] = 10, ['november'] = 11, ['december'] = 12, ['jan'] = 1, ['feb'] = 2, ['mar'] = 3, ['apr'] = 4, --['may'] = 5, -- long one would have caught this already ['jun'] = 6, ['jul'] = 7, ['aug'] = 8, ['sep'] = 9, ['oct'] = 10, ['nov'] = 11, ['dec'] = 12
}
local monthDays = { [1] = 31, [2] = 29, -- will check below [3] = 31, [4] = 30, [5] = 31, [6] = 30, [7] = 31, [8] = 31, [9] = 30, [10] = 31, [11] = 30, [12] = 31
}
function checkIfDayValid(day, month, year) -- First check that the month can have at least this many days if (day > monthDays[month]) then return false end -- February leap year check if (month == 2) then -- On Feb 29, if we don't have a year (incomplete date), assume 29 can be valid once every if (day == 29 and not year) then return true end -- On Feb 29, check for valid year - every 4 but not 100 but 400 if (day 0) and (year % 100 ~= 0) or (year % 400 == 0))) then return false end end return true
end
function checkIfMonthValid(month) return month ~= 0 and month <= 12 -- <0 never happens with [0-9] pattern
end
function checkIfYearValid(year) return year >= 1583 -- up to 9999
end
function checkIfHourValid(hour) return hour < 24 -- <0 never happens with [0-9] pattern
end
function checkIfMinuteValid(minute) return minute < 60 -- <0 never happens with [0-9] pattern
end
function checkIfSecondValid(second) return second < 60 -- <0 never happens with [0-9] pattern
end
local PARSERESULT_OKAY = 1
local PARSERESULT_FAIL = 2 -- whatever we encountered isn't expected for any pattern
local PARSERESULT_UNCRECOGNIZED = 3 -- 14 May 12, 2014 (all elements okay, no pattern)
local PARSERESULT_INCOMPLETE = 4 -- May 3
local PARSERESULT_INCOMPLETERANGE = 5 -- 3 May 2012 - June 2013
local PARSERESULT_INVALID = 6 -- May 32
local PARSERESULT_INVALIDRANGE = 7 -- May 3 - May 2
-- This will first verify that we have a valid date and time and then output an ISO datetime string
function checkAndOutput(year, month, day, hour, minute, second, year2, month2, day2, hour2, minute2, second2) local s if (year and not checkIfYearValid(year)) then return PARSERESULT_INVALID; end if (month and not checkIfMonthValid(month)) then return PARSERESULT_INVALID; end if (day and not checkIfDayValid(day, month, year)) then return PARSERESULT_INVALID; end if (hour and not checkIfHourValid(hour)) then return PARSERESULT_INVALID; end if (minute and not checkIfMinuteValid(minute)) then return PARSERESULT_INVALID; end if (second and not checkIfSecondValid(second)) then return PARSERESULT_INVALID; end if (year2 and not checkIfYearValid(year2)) then return PARSERESULT_INVALID; end if (month2 and not checkIfMonthValid(month2)) then return PARSERESULT_INVALID; end if (day2 and not checkIfDayValid(day2, month2, year2)) then return PARSERESULT_INVALID; end if (hour2 and not checkIfHourValid(hour2)) then return PARSERESULT_INVALID; end if (minute2 and not checkIfMinuteValid(minute2)) then return PARSERESULT_INVALID; end if (second2 and not checkIfSecondValid(second2)) then return PARSERESULT_INVALID; end -- Check that end date is actually after start date if (year2 and year) then if (year2 < year) then return PARSERESULT_INVALIDRANGE end if (year2 == year) then if (month2 and month) then if (month2 < month) then return PARSERESULT_INVALIDRANGE end if (month2 == month) then if (day2 and day) then if (day2 < day) then return PARSERESULT_INVALIDRANGE end -- TODO: compare time end end end end end -- Check that the date is actually complete even if valid if (month and month2 and not year) then return PARSERESULT_INCOMPLETERANGE end -- any of 'd-dM', 'dM-dM', 'Md-d', 'Md-Md' if (month and not year) then return PARSERESULT_INCOMPLETE end -- 'May', 'May 15', '15 May' if (month2 and not year2) then return PARSERESULT_INCOMPLETE end -- same but other end -- While technically there are more cases, none should have been matched and been given to us local date1, time1, date2, time2 -- time only if (second and not year) then time1 = string. format('%02d:%02d:%02d', hour, minute, second) elseif (minute and not year) then time1 = string. format('%02d:%02d', hour, minute) elseif (hour and not year) then time1 = string.