Module:Citation/CS1/Date validation: Difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
m Synch from sandbox; |
Synch from sandbox; |
||
Line 3: | Line 3: | ||
-- returns a number according to the month in a date: 1 for January, etc. Capitalization and spelling must be correct. If not a valid month, returns 0 |
-- returns a number according to the month in a date: 1 for January, etc. Capitalization and spelling must be correct. If not a valid month, returns 0 |
||
function get_month_number (month) |
local function get_month_number (month) |
||
local long_months = {['January']=1, ['February']=2, ['March']=3, ['April']=4, ['May']=5, ['June']=6, ['July']=7, ['August']=8, ['September']=9, ['October']=10, ['November']=11, ['December']=12}; |
local long_months = {['January']=1, ['February']=2, ['March']=3, ['April']=4, ['May']=5, ['June']=6, ['July']=7, ['August']=8, ['September']=9, ['October']=10, ['November']=11, ['December']=12}; |
||
local short_months = {['Jan']=1, ['Feb']=2, ['Mar']=3, ['Apr']=4, ['May']=5, ['Jun']=6, ['Jul']=7, ['Aug']=8, ['Sep']=9, ['Oct']=10, ['Nov']=11, ['Dec']=12}; |
local short_months = {['Jan']=1, ['Feb']=2, ['Mar']=3, ['Apr']=4, ['May']=5, ['Jun']=6, ['Jul']=7, ['Aug']=8, ['Sep']=9, ['Oct']=10, ['Nov']=11, ['Dec']=12}; |
||
Line 15: | Line 15: | ||
-- returns a number according to the sequence of seasons in a year: 1 for Winter, etc. Capitalization and spelling must be correct. If not a valid season, returns 0 |
-- returns a number according to the sequence of seasons in a year: 1 for Winter, etc. Capitalization and spelling must be correct. If not a valid season, returns 0 |
||
function get_season_number (season) |
local function get_season_number (season) |
||
local season_list = {['Winter']=1, ['Spring']=2, ['Summer']=3, ['Fall']=4, ['Autumn']=4} |
local season_list = {['Winter']=1, ['Spring']=2, ['Summer']=3, ['Fall']=4, ['Autumn']=4} |
||
local temp; |
local temp; |
||
Line 24: | Line 24: | ||
--returns true if month or season is valid (properly spelled, capitalized, abbreviated) |
--returns true if month or season is valid (properly spelled, capitalized, abbreviated) |
||
function is_valid_month_or_season (month_season) |
local function is_valid_month_or_season (month_season) |
||
if 0 == get_month_number (month_season) then -- if month text isn't one of the twelve months, might be a season |
if 0 == get_month_number (month_season) then -- if month text isn't one of the twelve months, might be a season |
||
if 0 == get_season_number (month_season) then -- not a month, is it a season? |
if 0 == get_season_number (month_season) then -- not a month, is it a season? |
||
Line 40: | Line 40: | ||
]] |
]] |
||
function is_valid_year(year) |
local function is_valid_year(year) |
||
if not is_set(year_limit) then |
if not is_set(year_limit) then |
||
year_limit = tonumber(os.date("%Y"))+1; -- global variable so we only have to fetch it once |
year_limit = tonumber(os.date("%Y"))+1; -- global variable so we only have to fetch it once |
||
Line 53: | Line 53: | ||
Where the two calendars overlap (1582 to approximately 1923) dates are assumed to be Gregorian. |
Where the two calendars overlap (1582 to approximately 1923) dates are assumed to be Gregorian. |
||
]] |
]] |
||
function is_valid_date (year, month, day) |
local function is_valid_date (year, month, day) |
||
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
||
local month_length; |
local month_length; |
||
Line 81: | Line 81: | ||
end |
end |
||
--[[--------------------------< I S _ V A L I D _ M O N T H _ R A N G E _ S T Y L E >-------------------------- |
|||
--[[ |
|||
Months in a range are expected to have the same style: Jan–Mar or October–December but not February–Mar or Jul–August. |
|||
There is a special test for May because it can be either short or long form. |
|||
Returns true when style for both months is the same |
|||
]] |
|||
local function is_valid_month_range_style (month1, month2) |
|||
local len1 = month1:len(); |
|||
local len2 = month2:len(); |
|||
if len1 == len2 then |
|||
⚫ | |||
elseif 'May' == month1 or 'May'== month2 then |
|||
return true; -- both months are long form so return true |
|||
elseif 3 == len1 or 3 == len2 then |
|||
return false; -- months are mixed form so return false |
|||
else |
|||
return true; -- both months are long form so return true |
|||
end |
|||
end |
|||
--[[--------------------------< I S _ V A L I D _ M O N T H _ S E A S O N _ R A N G E >------------------------ |
|||
Check a pair of months or seasons to see if both are valid members of a month or season pair. |
Check a pair of months or seasons to see if both are valid members of a month or season pair. |
||
Month pairs are expected to be left to right, earliest to latest in time. |
Month pairs are expected to be left to right, earliest to latest in time. |
||
⚫ | |||
Similarly, seasons are also left to right, earliest to latest in time. There is an oddity with seasons: winter is assigned a value of 1, spring 2, ..., |
|||
is made to see if |date=Fall-Winter yyyy (4-1) is the date. |
|||
⚫ | |||
]] |
]] |
||
function is_valid_month_season_range(range_start, range_end) |
local function is_valid_month_season_range(range_start, range_end) |
||
local range_start_number = get_month_number (range_start); |
local range_start_number = get_month_number (range_start); |
||
Line 109: | Line 136: | ||
local range_end_number = get_month_number (range_end); -- get end month number |
local range_end_number = get_month_number (range_end); -- get end month number |
||
if range_start_number < range_end_number then -- range_start is a month; does range_start precede range_end? |
if range_start_number < range_end_number then -- range_start is a month; does range_start precede range_end? |
||
if is_valid_month_range_style (range_start, range_end) then -- do months have the same style? |
|||
⚫ | |||
return true; -- proper order and same style |
|||
end |
|||
end |
end |
||
return false; -- range_start month number is greater than or equal to range end number; or range end isn't a month |
return false; -- range_start month number is greater than or equal to range end number; or range end isn't a month |
||
Line 131: | Line 160: | ||
COinS_date is date_string without anchor_year disambiguator if any |
COinS_date is date_string without anchor_year disambiguator if any |
||
]] |
]] |
||
function check_date (date_string) |
local function check_date (date_string) |
||
local year; -- assume that year2, months, and days are not used; |
local year; -- assume that year2, months, and days are not used; |
||
local year2=0; -- second year in a year range |
local year2=0; -- second year in a year range |
||
Line 184: | Line 213: | ||
day, month, year, day2, month2, anchor_year, year2=date_string:match("(%d%d?) +(%a+) +(%d%d%d%d?) – (%d%d?) +(%a+) +((%d%d%d%d?)%a?)"); |
day, month, year, day2, month2, anchor_year, year2=date_string:match("(%d%d?) +(%a+) +(%d%d%d%d?) – (%d%d?) +(%a+) +((%d%d%d%d?)%a?)"); |
||
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later |
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later |
||
if not is_valid_year(year2) then return false; end |
if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style |
||
month = get_month_number (month); |
month = get_month_number (month); |
||
month2 = get_month_number (month2); |
month2 = get_month_number (month2); |
||
Line 191: | Line 220: | ||
month, day, year, month2, day2, anchor_year, year2=date_string:match("(%a+) +(%d%d?), +(%d%d%d%d) – (%a+) +(%d%d?), +((%d%d%d%d)%a?)"); |
month, day, year, month2, day2, anchor_year, year2=date_string:match("(%a+) +(%d%d?), +(%d%d%d%d) – (%a+) +(%d%d?), +((%d%d%d%d)%a?)"); |
||
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later |
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later |
||
if not is_valid_year(year2) then return false; end |
if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style |
||
month = get_month_number (month); |
month = get_month_number (month); |
||
month2 = get_month_number (month2); |
month2 = get_month_number (month2); |
||
Line 216: | Line 245: | ||
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same |
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same |
||
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year |
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year |
||
if not((0 ~= get_month_number(month) and 0 ~= get_month_number(month2)) or |
if not((0 ~= get_month_number(month) and 0 ~= get_month_number(month2) and is_valid_month_range_style(month, month2)) or -- both must be month year, same month style |
||
(0 ~= get_season_number(month) and 0 ~= get_season_number(month2))) then return false; end |
(0 ~= get_season_number(month) and 0 ~= get_season_number(month2))) then return false; end -- or season year, not mixed |
||
elseif date_string:match ("^%a+–%a+ +[1-9]%d%d%d%a?$") then -- month/season range year; months separated by endash |
elseif date_string:match ("^%a+–%a+ +[1-9]%d%d%d%a?$") then -- month/season range year; months separated by endash |
||
Line 291: | Line 320: | ||
]] |
]] |
||
function p.dates(date_parameters_list) |
--function p.dates(date_parameters_list) |
||
local function dates(date_parameters_list) |
|||
local anchor_year; -- will return as nil if the date being tested is not |date= |
local anchor_year; -- will return as nil if the date being tested is not |date= |
||
local COinS_date; -- will return as nil if the date being tested is not |date= |
local COinS_date; -- will return as nil if the date being tested is not |date= |
||
local error_message =""; |
local error_message = ""; |
||
local |
local mismatch = 0; |
||
local good_date = false; |
|||
for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list |
for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list |
||
Line 326: | Line 357: | ||
end |
end |
||
end |
end |
||
⚫ | |||
end |
|||
--[[--------------------------< Y E A R _ D A T E _ C H E C K >------------------------------------------------ |
|||
⚫ | |||
Compare the value provided in |year= with the year value(s) provided in |date=. This function returns a numeric value: |
|||
0 - year value does not match the year value in date |
|||
1 - (default) year value matches the year value in date or one of the year values when date contains two years |
|||
2 - year value matches the year value in date when date is in the form YYYY-MM-DD and year is disambiguated (|year=YYYYx) |
|||
]] |
|||
local function year_date_check (year_string, date_string) |
|||
local year; |
|||
local date1; |
|||
local date2; |
|||
local result = 1; -- result of the test; assume that the test passes |
|||
year = year_string:match ('(%d%d%d%d?)'); |
|||
if date_string:match ('%d%d%d%d%-%d%d%-%d%d') and year_string:match ('%d%d%d%d%a') then --special case where date and year required YYYY-MM-DD and YYYYx |
|||
date1 = date_string:match ('(%d%d%d%d)'); |
|||
year = year_string:match ('(%d%d%d%d)'); |
|||
if year ~= date1 then |
|||
result = 0; -- years don't match |
|||
else |
|||
result = 2; -- years match; but because disambiguated, don't add to maint cat |
|||
end |
|||
elseif date_string:match ("%d%d%d%d?.-%d%d%d%d?") then -- any of the standard formats of date with two three- or four-digit years |
|||
date1, date2 = date_string:match ("(%d%d%d%d?).-(%d%d%d%d?)"); |
|||
if year ~= date1 and year ~= date2 then |
|||
result = 0; |
|||
end |
|||
elseif date_string:match ("%d%d%d%d[%s%-–]+%d%d") then -- YYYY-YY date ranges |
|||
local century; |
|||
date1, century, date2 = date_string:match ("((%d%d)%d%d)[%s%-–]+(%d%d)"); |
|||
date2 = century..date2; -- convert YY to YYYY |
|||
if year ~= date1 and year ~= date2 then |
|||
result = 0; |
|||
end |
|||
elseif date_string:match ("%d%d%d%d?") then -- any of the standard formats of date with one year |
|||
date1 = date_string:match ("(%d%d%d%d?)"); |
|||
if year ~= date1 then |
|||
result = 0; |
|||
end |
|||
end |
|||
⚫ | |||
end |
end |
||
return {dates = dates, year_date_check = year_date_check} -- return exported functions |
|||
⚫ |