Module:Citation/CS1/Date validation: Difference between revisions

synch from sandbox;
m>Trappist the monk
(Synch from sandbox;)
m>Trappist the monk
(synch from sandbox;)
Line 6: Line 6:
]]
]]


local is_set, in_array; -- imported function from selected Module:Citation/CS1/Utilities
local is_set, in_array; -- imported functions from selected Module:Citation/CS1/Utilities
 
local cfg; -- table of tables imported from slected Module:Citation/CS1/Configuration


--[=[-------------------------< I S _ V A L I D _ A C C E S S D A T E >----------------------------------------
--[=[-------------------------< I S _ V A L I D _ A C C E S S D A T E >----------------------------------------
Line 58: Line 58:


local 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};
return cfg.date_names['local'].long[month] or cfg.date_names['local'].short[month] or -- look for local names first
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};
cfg.date_names['en'].long[month] or cfg.date_names['en'].short[month] or -- failing that, look for English names
return long_months[month] or -- if month is the long-form name
0; -- not a recognized month name
short_months[month] or -- if month is the short-form name
0; -- misspelled, improper case, or not a month name
end
end


Line 88: Line 86:


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
Uses ISO DIS 8601 2016 part 2 §4.7  Divisions of a year for hemishpere-independent seasons:
21-24 = Spring, Summer, Autumn, Winter, independent of “Hemisphere”
These additional divisions not currently supported:
25-28 = Spring - Northern Hemisphere, Summer- Northern Hemisphere, Autumn - Northern Hemisphere, Winter - Northern Hemisphere
29-32 = Spring – Southern Hemisphere, Summer– Southern Hemisphere, Autumn – Southern Hemisphere, Winter - Southern Hemisphere
33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)
37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each)
40-41 = Semestral 1, Semestral-2 (6 months each)


]]
]]


local function get_season_number (season)
local function get_season_number (season)
local season_list = {['Winter']=21, ['Spring']=22, ['Summer']=23, ['Fall']=24, ['Autumn']=24}; -- make sure these numbers do not overlap month numbers
return cfg.date_names['local'].season[season] or -- look for local names first
local temp;
cfg.date_names['en'].season[season] or -- failing that, look for English names
temp=season_list[season];
0; -- not a recognized season name
if temp then return temp; end -- if season is a valid name return its number
return 0; -- misspelled, improper case, or not a season name
end
end


Line 106: Line 113:


local function is_proper_name (name)
local function is_proper_name (name)
local name_list = {['Christmas']=31}
return cfg.date_names['local'].named[name] or -- look for local names dates first
local temp;
cfg.date_names['en'].named[name] or -- failing that, look for English names
temp=name_list[name];
0; -- not a recognized named date
if temp then return temp; end -- if name is a valid name return its number
return 0; -- misspelled, improper case, or not a proper name
end
end


Line 211: Line 216:
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, ...,
All season ranges are accepted as valid because there are publishers out there who have published a Summer–Spring YYYY issue so ... ok
fall and autumn 4. Because winter can follow fall/autumn at the end of a calender year, a special test is made to see if |date=Fall-Winter yyyy (4-1) is the date.


]]
]]
Line 221: Line 225:
if 0 == range_start_number then -- is this a month range?
if 0 == range_start_number then -- is this a month range?
local range_start_number = get_season_number (range_start); -- not a month; is it a season? get start season number
range_start_number = get_season_number (range_start); -- not a month; is it a season? get start season number
range_end_number = get_season_number (range_end); -- get end season number
range_end_number = get_season_number (range_end); -- get end season number


if 0 ~= range_start_number then -- is start of range a season?
if (0 ~= range_start_number) and (0 ~= range_end_number) then
if range_start_number < range_end_number then -- range_start is a season
return true; -- any season pairing is accepted
return true; -- return true when range_end is also a season and follows start season; else false
end
if 24 == range_start_number and 21 == range_end_number then -- special case when season range is Fall-Winter or Autumn-Winter
return true;
end
end
end
return false; -- range_start is not a month or a season; or range_start is a season and range_end is not; or improper season sequence
return false; -- range_start and/or range_end is not a season
end
end
 
-- here when range_start is a month
range_end_number = get_month_number (range_end); -- get end month number
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?
Line 366: Line 365:
if 12 < tonumber(month) or 1 > tonumber(month) or 1582 > tonumber(year) or 0 == tonumber(day) then return false; end -- month or day number not valid or not Gregorian calendar
if 12 < tonumber(month) or 1 > tonumber(month) or 1582 > tonumber(year) or 0 == tonumber(day) then return false; end -- month or day number not valid or not Gregorian calendar
anchor_year = year;
anchor_year = year;
elseif date_string:match("^%a+ +[1-9]%d?, +[1-9]%d%d%d%a?$") then -- month-initial: month day, year
elseif date_string:match("^%a+ +[1-9]%d?, +[1-9]%d%d%d%a?$") then -- month-initial: month day, year
month, day, anchor_year, year=string.match(date_string, "(%a+)%s*(%d%d?),%s*((%d%d%d%d)%a?)");
month, day, anchor_year, year=string.match(date_string, "(%a+)%s*(%d%d?),%s*((%d%d%d%d?)%a?)");
month = get_month_number (month);
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
Line 381: Line 379:


elseif date_string:match("^[1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day-initial: day month year
elseif date_string:match("^[1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day-initial: day month year
day, month, anchor_year, year=string.match(date_string, "(%d%d*)%s*(%a+)%s*((%d%d%d%d)%a?)");
day, month, anchor_year, year=string.match(date_string, "(%d%d*)%s*(%a+)%s*((%d%d%d%d?)%a?)");
month = get_month_number (month);
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
Line 400: Line 398:
year2=year;
year2=year;


elseif mw.ustring.match(date_string, "^%a+ +[1-9]%d? [%-–] %a+ +[1-9]%d?, +[1-9]%d%d%d?%a?$") then -- month initial month-day-range: month day – month day, year;  uses spaced endash
elseif mw.ustring.match(date_string, "^%a+ +[1-9]%d? [%-–] %a+ +[1-9]%d?, +[1-9]%d%d%d%a?$") then -- month initial month-day-range: month day – month day, year;  uses spaced endash
month, day, month2, day2, anchor_year, year=mw.ustring.match(date_string, "(%a+) +(%d%d?) [%-–] (%a+) +(%d%d?), +((%d%d%d%d)%a?)");
month, day, month2, day2, anchor_year, year=mw.ustring.match(date_string, "(%a+) +(%d%d?) [%-–] (%a+) +(%d%d?), +((%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 408: Line 406:


elseif mw.ustring.match(date_string, "^[1-9]%d? +%a+ +[1-9]%d%d%d [%-–] [1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day initial month-day-year-range: day month year - day month year; uses spaced endash
elseif mw.ustring.match(date_string, "^[1-9]%d? +%a+ +[1-9]%d%d%d [%-–] [1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day initial month-day-year-range: day month year - day month year; uses spaced endash
day, month, year, day2, month2, anchor_year, year2=mw.ustring.match(date_string, "(%d%d?) +(%a+) +(%d%d%d%d?) [%-–] (%d%d?) +(%a+) +((%d%d%d%d?)%a?)");
day, month, year, day2, month2, anchor_year, year2=mw.ustring.match(date_string, "(%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) 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
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
Line 662: Line 660:


local source_patterns = { -- this table holds patterns that match allowed date formats used to extract date components
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)',
['dmy'] = '^(%d%d?)%s+(%a+)%s+(%d%d%d%d)$',
['mdy'] = '(%a+)%s+(%d%d?),%s+(%d%d%d%d)',
['mdy'] = '^(%a+)%s+(%d%d?),%s+(%d%d%d%d)$',
['ymd'] = '(%d%d%d%d)%-(%d%d)-(%d%d)',
['ymd'] = '^(%d%d%d%d)%-(%d%d)-(%d%d)$',
}
}


Line 723: Line 721:


Date ranges, season dates, proper name dates are not currently supported.
Date ranges, season dates, proper name dates are not currently supported.
For i18n:  This code works only at en.wiki because os.date() doesn't support any languages other than English.
mw.getContentLanguage():formatDate() will work at non-English wikis only when the date format is yyyy-mm-dd. This is
the same issue that plagues is_valid_accessdate()
It is possible that a solution like that written for ht:Module:Citation/CS1/Date_validation date_name_xlate() could be applied to this problem


]]
]]
Line 736: Line 740:
end
end
for param_name, param_val in pairs(date_parameters_list) do -- for each date-holding parameter in the list
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 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
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
param_val = ''; -- set to empty string so we don't process this date
end
end
for source, pattern in pairs(source_patterns) do
for source, pattern in pairs (source_patterns) do
if param_val:match(pattern) then
if param_val:match (pattern) then
if 'ymd' == source then
if 'ymd' == source then
get_ymd_date_parts (param_val, source_date); -- get the date parts into the source_date table
get_ymd_date_parts (param_val, source_date); -- get the date parts into the source_date table
Line 791: Line 795:
end
end
end
end
return result; -- so we know if  
return result; -- so we know if any hyphens were replaced
end
end
--[[-------------------------< D A T E _ N A M E _ X L A T E >------------------------------------------------
Attempts to translate English month names to local-language month names using names supplied by MediaWiki's
date parser function.  This is simple name-for-name replacement and may not work for all languages.
]]
local function date_name_xlate (date_parameters_list)
local xlate;
local mode; -- long or short month names
local modified = false;
local date;
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
date = param_val;
for month in mw.ustring.gmatch (date, '%a+') do -- iterate through all dates in the date (single date or date range)
if cfg.date_names.en.long[month] then
mode = 'F'; -- English name is long so use long local name
elseif cfg.date_names.en.short[month] then
mode = 'M'; -- English name is short so use short local name
else
mode = nil; -- not an English month name; could be local language month name or an English season name
end
if mode then -- might be a season
xlate = mw.getContentLanguage():formatDate(mode, '1' .. month); -- translate the month name to this local language
date = mw.ustring.gsub (date, month, xlate); -- replace the English with the translation
date_parameters_list[param_name] = date; -- save the translated date
modified = true;
end
end
end
end
return modified;
end




Line 801: Line 845:
]]
]]


local function set_selected_modules (utilities_page_ptr)
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)
is_set = utilities_page_ptr.is_set; -- import functions from select Module:Citation/CS1/Utilities module
is_set = utilities_page_ptr.is_set; -- import functions from selected Module:Citation/CS1/Utilities module
in_array = utilities_page_ptr.in_array; -- import functions from select Module:Citation/CS1/Utilities module
in_array = utilities_page_ptr.in_array; -- import functions from selected Module:Citation/CS1/Utilities module
cfg = cfg_table_ptr; -- import tables from selected Module:Citation/CS1/Configuration
end
end


Line 813: Line 858:
reformat_dates = reformat_dates,
reformat_dates = reformat_dates,
date_hyphen_to_dash = date_hyphen_to_dash,
date_hyphen_to_dash = date_hyphen_to_dash,
date_name_xlate = date_name_xlate,
set_selected_modules = set_selected_modules
set_selected_modules = set_selected_modules
}
}
Anonymous user