Module:Citation/CS1/Date validation: திருத்தங்களுக்கு இடையிலான வேறுபாடு
உள்ளடக்கம் நீக்கப்பட்டது உள்ளடக்கம் சேர்க்கப்பட்டது
Synch from sandbox; |
|||
வரிசை 1:
local p = {}
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local is_set, in_array; -- imported function from selected Module:Citation/CS1/Utilities
--[[--------------------------< I S _ V A L I D _ A C C E S S D A T E >----------------------------------------
வரி 97 ⟶ 104:
return true;
end
--[[--------------------------< I S _ V A L I D _ Y E A R >----------------------------------------------------
வரி 104 ⟶ 110:
]]
local year_limit;
local function is_valid_year(year)
if not is_set(year_limit) then
வரி 112 ⟶ 118:
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
than next year; else returns false.
Assumes Julian calendar prior to year 1582 and Gregorian calendar thereafter. Accounts for Julian calendar leap
years before 1582 and Gregorian leap years after 1582. Where the two calendars overlap (1582 to approximately
1923) dates are assumed to be Gregorian.
]]
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 month_length;
if not is_valid_year(year) then -- no farther into the future than next year
return false;
end
month_length = 28; -- then 28 days unless
if 1582 > tonumber(year) then -- Julian calendar
if 0==(year%4) then
month_length = 29;
end
else -- Gregorian calendar
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
end
end
else
month_length=days_in_month[
end
வரி 213 ⟶ 225:
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
determined to be a valid date format. The question of what to do with
The date parts in the input table are converted to an ISO 8601 conforming date string:
வரி 258 ⟶ 270:
if input.year ~= input.year2 then -- season year – season year range or season year–year
tCOinS_date.rftssn = season[input.month]; -- start of range season; keep this?
if 0~= input.month2 then
tCOinS_date.rftchron = string.format ('%s %s – %s %s', season[input.month], input.year, season[input.month2], input.year2);
end
வரி 296 ⟶ 308:
--[[--------------------------< 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
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
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:
வரி 310 ⟶ 324:
true, anchor_year, COinS_date
anchor_year can be used in CITEREF anchors
COinS_date is ISO 8601 format date; see make_COInS_date()
]]
local function check_date (date_string, tCOinS_date)
local year; -- assume that year2, months, and days are not used;
வரி 325 ⟶ 340:
if date_string:match("^%d%d%d%d%-%d%d%-%d%d$") then -- year-initial numerical year month day format
year, month, day=string.match(date_string, "(%d%d%d%d)%-(%d%d)%-(%d%d)");
if 12 < tonumber(month) or 1 > tonumber(month) or
anchor_year = year;
வரி 415 ⟶ 430:
end
elseif date_string:match ("^%a+–%a+ +[1-9]%d%d%d%a?$") then
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
வரி 461 ⟶ 476:
else
return false; -- date format not one of the MOS:DATE approved formats
end
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)
result=is_valid_date(year,month,day);
வரி 482 ⟶ 497:
if false == result then return false; end
if nil ~= tCOinS_date then -- this table only passed into this function when testing |date= parameter values
வரி 490 ⟶ 502:
end
return true, anchor_year; -- format is good and date string represents a real date
end
--[[--------------------------< D A T E S >--------------------------------------------------------------------
வரி 509 ⟶ 521:
local COinS_date; -- will return as nil if the date being tested is not |date=
local error_message = "";
local good_date = false;
for k, v in pairs(date_parameters_list) do
if is_set(v) then
if v:match("^c%. [1-9]%d%d%d?%a?$") then
local year = v:match("c%. ([1-9]%d%d%d?)%a?");
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
வரி 522 ⟶ 533:
good_date = is_valid_year(year);
end
elseif 'date'==k then
if v:match("^n%.d%.%a?") then
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
good_date, anchor_year, COinS_date = true, v:match("((nd)%a?)"); --"nd"; no error when date parameter is set to no date
else
good_date, anchor_year, COinS_date = check_date (v, tCOinS_date);
end
elseif 'access-date'==k then
good_date = check_date (v);
if true == good_date then
good_date = is_valid_accessdate (v);
end
else
good_date = check_date (v);
end
if false==good_date then
if is_set(error_message) then
error_message=error_message .. ", ";
end
error_message=error_message .. "|" .. k .. "=";
end
end
end
return anchor_year, error_message; -- and done
end
--[[--------------------------< Y E A R _ D A T E _ C H E C K >------------------------------------------------
வரி 567 ⟶ 578:
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 both date and year are required YYYY-MM-DD and YYYYx
date1 = date_string:match ('(%d%d%d%d)');
year = year_string:match ('(%d%d%d%d)');
வரி 576 ⟶ 587:
end
elseif date_string:match ("%d%d%d%d?.-%d%d%d%d?") then -- any of the standard range 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
வரி 582 ⟶ 593:
end
elseif date_string:match ("%d%d%d%
local century;
date1, century, date2 = date_string:match ("((%d%d)%d%d)[%s%-–]+(%d%d)");
வரி 595 ⟶ 606:
result = 0;
end
else
result = 0; -- no recognizable year in date
end
return result;
end
--[[-------------------------< R E F O R M A T T A B L E S >------------------------------------------------
These table are used exclusively for reformatting dates
]]
local source_patterns = { -- this table holds patterns that match allowed date formats used to extract date components
['dmy'] = '(%d%d?)%s+(%a+)%s+(%d%d%d%d)',
['mdy'] = '(%a+)%s+(%d%d?),%s+(%d%d%d%d)',
['ymd'] = '(%d%d%d%d)%-(%d%d)-(%d%d)',
}
local short_formats = { -- this table holds format strings used by os.date() for short month names
['dmy'] = '%e %b %Y',
['mdy'] = '%b %e, %Y',
['ymd'] = '%F',
}
local long_formats = { -- this table holds format strings used by os.date() for long month names
['dmy'] = '%e %B %Y',
['mdy'] = '%B %e, %Y',
['ymd'] = '%F',
}
--[[-------------------------< G E T _ D M Y _ D A T E _ P A R T S >------------------------------------------
extracts year, month and day from DMY formatted date, places them in the source_date table, and returns.
]]
local function get_dmy_date_parts (date, source_date)
source_date.day, source_date.month, source_date.year = date:match (source_patterns['dmy']); -- get date components as strings
source_date.month = get_month_number (source_date.month); -- get month number
end
--[[-------------------------< G E T _ M D Y _ D A T E _ P A R T S >------------------------------------------
extracts year, month and day from MDY formatted date, places them in the source_date table, and returns.
]]
local function get_mdy_date_parts (date, source_date)
source_date.month, source_date.day, source_date.year = date:match (source_patterns['mdy']); -- get date components as strings
source_date.month = get_month_number (source_date.month); -- get month number
end
--[[-------------------------< G E T _ Y M D _ D A T E _ P A R T S >------------------------------------------
extracts year, month and day from YMD formatted date, places them in the source_date table, and returns.
]]
local function get_ymd_date_parts (date, source_date)
source_date.year, source_date.month, source_date.day = date:match (source_patterns['ymd']); -- get date components as strings
end
--[[-------------------------< R E F O R M A T _ D A T E S >--------------------------------------------------
Reformats existing dates into the format specified by format and short.
format is one of several keywords: dmy, dmy-all, mdy, mdy-all, ymd, ymd-all. The all version includes access- and
archive-dates; otherwise these dates are not reformatted
Date ranges, season dates, proper name dates are not currently supported.
]]
local function reformat_dates (date_parameters_list, format, short)
local all = false; -- set to false to skip access- and archive-dates
local format_str;
local source_date = {};
if format:match('%a+%-all') then
format = format:match('(%a+)%-all'); -- extract the format
all = true; -- set to true to format access- and archive-dates
end
for param_name, param_val in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set(param_val) then -- if the parameter has a value
if not all and in_array (param_name, {'access-date', 'archive-date'}) then -- if access- or archive-date and format not xxx-all
param_val = ''; -- set to empty string so we don't process this date
end
for source, pattern in pairs(source_patterns) do
if param_val:match(pattern) then
if 'ymd' == source then
get_ymd_date_parts (param_val, source_date); -- get the date parts into the source_date table
elseif 'dmy' == source then
get_dmy_date_parts (param_val, source_date); -- get the date parts into the source_date table
elseif 'mdy' == source then
get_mdy_date_parts (param_val, source_date); -- get the date parts into the source_date table
end
if 'ymd' == format and 1582 > tonumber(source_date.year) then -- ymd format dates not allowed before 1582
return false; -- abandon reformatting
end
if short then
format_str = short_formats[format];
else
format_str = long_formats[format];
end
date_parameters_list[param_name] = os.date (format_str, os.time(source_date)); -- convert date and save
end
end
end
end
return true; -- declare success and done
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (utilities_page_ptr)
is_set = utilities_page_ptr.is_set; -- import functions from select Module:Citation/CS1/Utilities module
in_array = utilities_page_ptr.in_array; -- import functions from select Module:Citation/CS1/Utilities module
end
return { -- return exported functions
dates = dates,
year_date_check = year_date_check,
reformat_dates = reformat_dates,
set_selected_modules = set_selected_modules
}
| |||