మాడ్యూల్:Citation/CS1/Date validation: కూర్పుల మధ్య తేడాలు
Content deleted Content added
Arjunaraoc (చర్చ | రచనలు) చి change to regexp that worked previously |
sync from sandbox; |
||
పంక్తి 55:
return false; -- accessdate out of range
end
end
Line 90 ⟶ 77:
--[[--------------------------< G E T _
returns a number according to the
If not a valid ]]
local function get_month_number (month)
return cfg.date_names['local'].long[month] or cfg.date_names['local'].short[month] or -- look for local names first
cfg.date_names['en'].long[month] or cfg.date_names['en'].short[month] or -- failing that, look for English names
0; -- not a recognized month name
end
--[[--------------------------< G E T _ S E A S O N _ N U M B E R >--------------------------------------------
returns a number according to the sequence of seasons in a year: 21 for Spring, etc. Capitalization and spelling
must be correct. If not a valid season, returns 0.
21-24 = Spring, Summer, Autumn, Winter, independent of “Hemisphere”
returns 0 when <param> is not |date=
Season numbering is defined by Extended Date/Time Format (EDTF) Specification (https://www.loc.gov/standards/datetime/)
which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using
numbers 21-41. cs1|2 only supports generic seasons. EDTF does support the distinction between north and south
hemispere seasons but cs1|2 has no way to make that distinction.
These additional divisions not currently supported:
Line 106 ⟶ 113:
]]
local function get_season_number (season, param)
if 'date' ~= param then
return 0; -- season dates only supported by |date=
end
return cfg.date_names['local'].season[season] or -- look for local names first
cfg.date_names['en'].season[season] or -- failing that, look for English names
Line 113 ⟶ 123:
--[[--------------------------<
returns a
must be correct. If not a valid quarter, returns 0.
33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)
returns 0 when <param> is not |date=
Quarter numbering is defined by Extended Date/Time Format (EDTF) Specification (https://www.loc.gov/standards/datetime/)
which became part of ISO 8601 in 2019. See '§Sub-year groupings'. The standard defines various divisions using
numbers 21-41. cs1|2 only supports generic seasons and quarters.
These additional divisions not currently supported:
37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each)
40-41 = Semestral 1, Semestral-2 (6 months each)
]]
local function
if 'date' ~= param then
return 0; -- quarter dates only supported by |date=
end
quarter = mw.ustring.gsub (quarter, ' +', ' '); -- special case replace multiple space chars with a single space char
return cfg.date_names['local'].quarter[quarter] or -- look for local names first
cfg.date_names['en'].quarter[quarter] or -- failing that, look for English names
0; -- not a recognized quarter name
end
--[[--------------------------< G E T _ P R O P E R _ N A M E _ N U M B E R >----------------------------------
returns a non-zero number if date contains a recognized proper-name. Capitalization and spelling must be correct.
returns 0 when <param> is not |date=
]]
local function get_proper_name_number (name, param)
if 'date' ~= param then
return 0; -- proper-name dates only supported by |date=
end
return cfg.date_names['local'].named[name] or -- look for local names dates first
cfg.date_names['en'].named[name] or -- failing that, look for English names
Line 126 ⟶ 170:
--[[--------------------------<
]]
local function
local num;
local funcs = {get_month_number, get_season_number, get_quarter_number, get_proper_name_number}; -- list of functions to execute in order
for _, func in ipairs (funcs) do -- spin through the function list
num = func (element, param); -- call the function and get the returned number
if 0 ~= num then -- non-zero when valid month season quarter
return num; -- return that number
end
end
return
end
Line 144 ⟶ 193:
--[[--------------------------< I S _ V A L I D _ Y E A R >----------------------------------------------------
Function gets current year from the server and compares it to year from a citation parameter. Years more than one
year in the future are not acceptable. ]]
local function is_valid_year (year)
if not is_set(year_limit) then
year_limit = tonumber(os.date("%Y"))+1; -- global variable so we only have to fetch it once
Line 159 ⟶ 209:
--[[--------------------------< 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.
Line 281 ⟶ 332:
the output table receives:
rftdate: an IS8601 formatted date
rftchron: a free-form version of the date, usually without year which is in rftdate (season ranges and
rftssn: one of four season keywords: winter, spring, summer, fall (lowercase)
rftquarter: one of four values: 1, 2, 3, 4
]]
Line 306 ⟶ 358:
date = string.format ('%.4d/%.4d', tonumber(input.year), tonumber(input.year2)) -- assemble the date range
end
if 20 < tonumber(input.month) then -- if season or
local season = {[24]='winter', [21]='spring', [22]='summer', [23]='fall', [33]='1', [34]='2', [35]='3', [36]='4', [98]='Easter', [99]='Christmas'}; -- seasons lowercase, no autumn; proper
if 0 == input.month2 then -- single season date
if
tCOinS_date.rftchron = season[input.month]; -- proper
elseif 30 <tonumber(input.month) then
tCOinS_date.rftquarter = season[input.month]; -- quarters
else
tCOinS_date.rftssn = season[input.month]; -- seasons
Line 373 ⟶ 427:
['Md-dy'] = {'^(%D-) +([1-9]%d?)[%-–]([1-9]%d?), +((%d%d%d%d)%a?)$', 'm', 'd', 'd2', 'a', 'y'},
-- day-initial: day month year
['dMy'] = {'^([1-9]%d?)
-- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed; not supported at en.wiki
-- ['yMd'] = {'^((%d%d%d%d?)%a?) +(%D-) +(%d%d?)$', 'a', 'y', 'm', 'd'},
Line 392 ⟶ 446:
-- month/season range year; months separated by endash
['M-My'] = {'^(%D-)[%-–](%D-) +((%d%d%d%d)%a?)$', 'm', 'm2', 'a', 'y'},
-- month/season year or proper-name year; quarter year when First Quarter YYYY etc
['My'] = {'^([^%d–]-) +((%d%d%d%d)%a?)$', 'm', 'a', 'y'}, -- this way because endash is a member of %D; %D- will match January–March 2019 when it shouldn't
-- these date formats cannot be converted
-- ['Q,y'] = {'^(Q%a* +[1-4]), +((%d%d%d%d)%a?)$'}, -- Quarter n, yyyy
['Sy4-y2'] = {'^(%D-) +((%d%d)%d%d)[%-–]((%d%d)%a?)$'}, -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash
['Sy-y'] = {'^(%D-) +(%d%d%d%d)[%-–]((%d%d%d%d)%a?)$'}, -- special case Winter/Summer year-year; year separated with unspaced endash
Line 425 ⟶ 482:
]]
--local function check_date (date_string, tCOinS_date, test_accessdate)
local function check_date (date_string, param, tCOinS_date)
local year; -- assume that year2, months, and days are not used;
local year2=0; -- second year in a year range
Line 440 ⟶ 498:
anchor_year = year;
-- elseif mw.ustring.match(date_string, patterns['Q,y'][1]) then -- quarter n, year; here because much the same as Mdy
-- month, anchor_year, year=mw.ustring.match(date_string, patterns['Q,y'][1]);
-- if not is_valid_year(year) then return false; end
-- month = get_quarter_number (month, param); -- get quarter number or nil
-- if not month then return false; end -- not valid whatever it is
elseif mw.ustring.match(date_string, patterns['Mdy'][1]) then -- month-initial: month day, year
month, day, anchor_year, year=mw.ustring.match(date_string, patterns['Mdy'][1]);
Line 546 ⟶ 610:
year2=year;
elseif mw.ustring.match(date_string, patterns['My'][1]) then -- month/season
month, anchor_year, year=mw.ustring.match(date_string, patterns['My'][1]);
if not is_valid_year(year) then return false; end
month = get_element_number (month, param); -- get month season quarter proper-name number or nil
if
elseif mw.ustring.match(date_string, patterns['y-y'][1]) then -- Year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999
Line 583 ⟶ 641:
end
if
if 0 ~= year and 0 ~= month and 0 ~= day and -- all parts of a single date required
0 == year2 and 0 == month2 and 0 == day2 then -- none of these; accessdate must not be a range
Line 656 ⟶ 714:
good_date, anchor_year, COinS_date = true, v.val:match("((nd)%a?)"); --"nd"; no error when date parameter is set to no date
else
good_date, anchor_year, COinS_date = check_date (v.val, k, tCOinS_date); -- go test the date
end
elseif 'year'==k then -- if the parameter is |year= it should hold only a year value
Line 662 ⟶ 720:
good_date, anchor_year, COinS_date = true, v.val:match("((%d+)%a?)");
end
elseif 'embargo'==k then -- if the parameter is |embargo=
good_date = check_date (v.val); -- go test the date
Line 670 ⟶ 726:
end
else -- any other date-holding parameter
good_date = check_date (v.val, k);
end
if false==good_date then -- assemble one error message so we don't add the tracking category multiple times
Line 853 ⟶ 909:
[patterns[pattern_idx][8] or 'x'] = c7;
};
if t.a then -- if this date has an anchor year capture
t.y = t.a; -- use the anchor year capture when reassembling the date
end
if tonumber(t.m) then -- if raw month is a number (converting from ymd)
|