Module:Citation/CS1/Date validation: Difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
Synch from sandbox; |
Synch from sandbox; |
||
Line 97: | Line 97: | ||
return true; |
return true; |
||
end |
end |
||
--[[--------------------------< I S _ V A L I D _ Y E A R >---------------------------------------------------- |
--[[--------------------------< I S _ V A L I D _ Y E A R >---------------------------------------------------- |
||
Line 112: | Line 111: | ||
end |
end |
||
--[[--------------------------< I S _ V A L I D _ D A T E >---------------------------------------------------- |
|||
--[[ |
|||
Returns true if day is less than or equal to the number of days in month and year is no farther into the future |
Returns true if day is less than or equal to the number of days in month and year is no farther into the future |
||
than next year; else returns false. |
|||
⚫ | |||
years before 1582 and Gregorian leap years after 1582. Where the two calendars overlap (1582 to approximately |
|||
⚫ | |||
⚫ | |||
⚫ | |||
]] |
]] |
||
local 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; |
||
if not is_valid_year(year) then -- no farther into the future than next year |
if not is_valid_year(year) then -- no farther into the future than next year |
||
return false; |
return false; |
||
end |
end |
||
month = tonumber(month); -- required for YYYY-MM-DD dates |
|||
⚫ | |||
if (2==month) then -- if February |
|||
⚫ | |||
if 1582 > tonumber(year) then -- Julian calendar |
|||
if 0==(year%4) then |
if 0==(year%4) then |
||
month_length = 29; |
month_length = 29; |
||
end |
end |
||
else -- Gregorian calendar |
else -- Gregorian calendar |
||
if (0==(year%4) and (0~=(year%100) or 0==(year%400))) then -- is a leap year? |
if (0==(year%4) and (0~=(year%100) or 0==(year%400))) then -- is a leap year? |
||
month_length = 29; -- if leap year then 29 days in February |
month_length = 29; -- if leap year then 29 days in February |
||
end |
end |
||
end |
end |
||
else |
else |
||
month_length=days_in_month[ |
month_length=days_in_month[month]; |
||
end |
end |
||
Line 213: | Line 218: | ||
This function receives a table of date parts for one or two dates and an empty table reference declared in |
This function receives a table of date parts for one or two dates and an empty table reference declared in |
||
Module:Citation/CS1. The function is called only for |date= parameters and only if the |date=<value> is |
Module:Citation/CS1. The function is called only for |date= parameters and only if the |date=<value> is |
||
determined to be a valid date format. The question of what to do with |
determined to be a valid date format. The question of what to do with invalid date formats is not answered here. |
||
The date parts in the input table are converted to an ISO 8601 conforming date string: |
The date parts in the input table are converted to an ISO 8601 conforming date string: |
||
Line 296: | Line 301: | ||
--[[--------------------------< C H E C K _ D A T E >---------------------------------------------------------- |
--[[--------------------------< C H E C K _ D A T E >---------------------------------------------------------- |
||
Check date format to see that it is one of the formats approved by WP:DATESNO or WP:DATERANGE. Exception: only |
Check date format to see that it is one of the formats approved by WP:DATESNO or WP:DATERANGE. Exception: only |
||
Additionally, check the date to see that it is a real date: no 31 in 30-day |
allowed range separator is endash. Additionally, check the date to see that it is a real date: no 31 in 30-day |
||
months; no 29 February when not a leap year. Months, both long-form and three character abbreviations, and seasons |
|||
must be spelled correctly. Future years beyond next year are not allowed. |
|||
If the date fails the format tests, this function returns false and does not return values for anchor_year and |
If the date fails the format tests, this function returns false and does not return values for anchor_year and |
||
COinS_date. When this happens, the date parameter is used in the COinS metadata and the CITEREF identifier gets |
|||
its year from the year parameter if present otherwise CITEREF does not get a date value. |
|||
Inputs: |
Inputs: |
||
Line 310: | Line 317: | ||
true, anchor_year, COinS_date |
true, anchor_year, COinS_date |
||
anchor_year can be used in CITEREF anchors |
anchor_year can be used in CITEREF anchors |
||
COinS_date is date_string without anchor_year disambiguator if any -- this is being obsoleted. In future: |
|||
COinS_date is ISO 8601 format date; see make_COInS_date() |
COinS_date is ISO 8601 format date; see make_COInS_date() |
||
]] |
]] |
||
local function check_date (date_string, tCOinS_date) |
local function check_date (date_string, tCOinS_date) |
||
local year; -- assume that year2, months, and days are not used; |
local year; -- assume that year2, months, and days are not used; |
||
Line 415: | Line 423: | ||
end |
end |
||
elseif date_string:match ("^%a+–%a+ +[1-9]%d%d%d%a?$") then |
elseif date_string:match ("^%a+–%a+ +[1-9]%d%d%d%a?$") then -- month/season range year; months separated by endash |
||
month, month2, anchor_year, year=date_string:match ("(%a+)–(%a+)%s*((%d%d%d%d)%a?)"); |
month, month2, anchor_year, year=date_string:match ("(%a+)–(%a+)%s*((%d%d%d%d)%a?)"); |
||
if (not is_valid_month_season_range(month, month2)) or (not is_valid_year(year)) then return false; end |
if (not is_valid_month_season_range(month, month2)) or (not is_valid_year(year)) then return false; end |
||
Line 461: | Line 469: | ||
else |
else |
||
return false; -- date format not one of the MOS:DATE approved formats |
return false; -- date format not one of the MOS:DATE approved formats |
||
end |
end |
||
local result=true; -- check whole dates for validity; assume true because not all dates will go through this test |
local result=true; -- check whole dates for validity; assume true because not all dates will go through this test |
||
if 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 == day2 then -- YMD (simple whole date) |
if 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 == day2 then -- YMD (simple whole date) |
||
result=is_valid_date(year,month,day); |
result=is_valid_date(year,month,day); |
||
Line 482: | Line 490: | ||
if false == result then return false; end |
if false == result then return false; end |
||
-- if here, then date_string is valid; get coins_date from date_string (leave CITEREF disambiguator) ... |
|||
-- coins_date=date_string:match("^(.+%d)%a?$"); -- last character of valid disambiguatable date is always a digit |
|||
-- coins_date= mw.ustring.gsub(coins_date, "–", "-" ); -- ... and replace any ndash with a hyphen |
|||
if nil ~= tCOinS_date then -- this table only passed into this function when testing |date= parameter values |
if nil ~= tCOinS_date then -- this table only passed into this function when testing |date= parameter values |
||
Line 490: | Line 495: | ||
end |
end |
||
return true, anchor_year; -- format is good and date string represents a real date |
return true, anchor_year; -- format is good and date string represents a real date |
||
-- return true, anchor_year, coins_date; -- format is good and date string represents a real date |
|||
end |
end |
||
--[[--------------------------< D A T E S >-------------------------------------------------------------------- |
--[[--------------------------< D A T E S >-------------------------------------------------------------------- |
||
Line 509: | Line 514: | ||
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 mismatch = 0; |
|||
local good_date = false; |
local good_date = false; |
||
for k, v in pairs(date_parameters_list) do |
for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list |
||
if is_set(v) then |
if is_set(v) then -- if the parameter has a value |
||
if v:match("^c%. [1-9]%d%d%d?%a?$") then |
if v:match("^c%. [1-9]%d%d%d?%a?$") then -- special case for c. year or with or without CITEREF disambiguator - only |date= and |year= |
||
local year = v:match("c%. ([1-9]%d%d%d?)%a?"); |
local year = v:match("c%. ([1-9]%d%d%d?)%a?"); -- get the year portion so it can be tested |
||
if 'date'==k then |
if 'date'==k then |
||
anchor_year, COinS_date = v:match("((c%. [1-9]%d%d%d?)%a?)"); -- anchor year and COinS_date only from |date= parameter |
anchor_year, COinS_date = v:match("((c%. [1-9]%d%d%d?)%a?)"); -- anchor year and COinS_date only from |date= parameter |
||
Line 522: | Line 526: | ||
good_date = is_valid_year(year); |
good_date = is_valid_year(year); |
||
end |
end |
||
elseif 'date'==k then |
elseif 'date'==k then -- if the parameter is |date= |
||
if v:match("^n%.d%.%a?") then |
if v:match("^n%.d%.%a?") then -- if |date=n.d. with or without a CITEREF disambiguator |
||
good_date, anchor_year, COinS_date = true, v:match("((n%.d%.)%a?)"); --"n.d."; no error when date parameter is set to no date |
good_date, anchor_year, COinS_date = true, v:match("((n%.d%.)%a?)"); --"n.d."; no error when date parameter is set to no date |
||
elseif v:match("^nd%a?$") then |
elseif v:match("^nd%a?$") then -- if |date=nd with or without a CITEREF disambiguator |
||
good_date, anchor_year, COinS_date = true, v:match("((nd)%a?)"); --"nd"; no error when date parameter is set to no date |
good_date, anchor_year, COinS_date = true, v:match("((nd)%a?)"); --"nd"; no error when date parameter is set to no date |
||
else |
else |
||
good_date, anchor_year, COinS_date = check_date (v, tCOinS_date); |
good_date, anchor_year, COinS_date = check_date (v, tCOinS_date); -- go test the date |
||
end |
end |
||
elseif 'access-date'==k then |
elseif 'access-date'==k then -- if the parameter is |date= |
||
good_date = check_date (v); |
good_date = check_date (v); -- go test the date |
||
if true == good_date then |
if true == good_date then -- if the date is a valid date |
||
good_date = is_valid_accessdate (v); |
good_date = is_valid_accessdate (v); -- is Wikipedia start date < accessdate < tomorrow's date? |
||
end |
end |
||
else |
else -- any other date-holding parameter |
||
good_date = check_date (v); |
good_date = check_date (v); -- go test the date |
||
end |
end |
||
if false==good_date then |
if false==good_date then -- assemble one error message so we don't add the tracking category multiple times |
||
if is_set(error_message) then |
if is_set(error_message) then -- once we've added the first portion of the error message ... |
||
error_message=error_message .. ", "; |
error_message=error_message .. ", "; -- ... add a comma space separator |
||
end |
end |
||
error_message=error_message .. "|" .. k .. "="; |
error_message=error_message .. "|" .. k .. "="; -- add the failed parameter |
||
end |
end |
||
end |
end |
||
end |
end |
||
-- return anchor_year, COinS_date, error_message, mismatch; -- and done |
|||
return anchor_year, error_message; -- and done |
return anchor_year, error_message; -- and done |
||
end |
end |
||
--[[--------------------------< Y E A R _ D A T E _ C H E C K >------------------------------------------------ |
--[[--------------------------< Y E A R _ D A T E _ C H E C K >------------------------------------------------ |