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

    m>Trappist the monk
    (Synch from sandbox;)
    m>Trappist the monk
    (Synch from sandbox;)
    Line 1: Line 1:


    local p = {}
    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 >----------------------------------------
    --[[--------------------------< I S _ V A L I D _ A C C E S S D A T E >----------------------------------------
    Line 103: Line 110:


    ]]
    ]]
     
    local year_limit;
    local 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
    Line 263: Line 270:
    if input.year ~= input.year2 then -- season year – season year range or season year–year
    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?
    tCOinS_date.rftssn = season[input.month]; -- start of range season; keep this?
    if 0~= month2 then
    if 0~= input.month2 then
    tCOinS_date.rftchron = string.format ('%s %s – %s %s', season[input.month], input.year, season[input.month2], input.year2);
    tCOinS_date.rftchron = string.format ('%s %s – %s %s', season[input.month], input.year, season[input.month2], input.year2);
    end
    end
    Line 333: Line 340:
    if date_string:match("^%d%d%d%d%-%d%d%-%d%d$") then -- year-initial numerical year month day format
    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)");
    year, month, day=string.match(date_string, "(%d%d%d%d)%-(%d%d)%-(%d%d)");
    if 12 < tonumber(month) or 1 > tonumber(month) or 1583 > tonumber(year) then return false; end -- month 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;


    Line 571: Line 578:
    year = year_string:match ('(%d%d%d%d?)');
    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
    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)');
    date1 = date_string:match ('(%d%d%d%d)');
    year = year_string:match ('(%d%d%d%d)');
    year = year_string:match ('(%d%d%d%d)');
    Line 580: Line 587:
    end
    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
    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?)");
    date1, date2 = date_string:match ("(%d%d%d%d?).-(%d%d%d%d?)");
    if year ~= date1 and year ~= date2 then
    if year ~= date1 and year ~= date2 then
    Line 586: Line 593:
    end
    end


    elseif date_string:match ("%d%d%d%d[%s%-–]+%d%d") then -- YYYY-YY date ranges
    elseif date_string:match ("%d%d%d%d–%d%d") then -- YYYY-YY date ranges
    local century;
    local century;
    date1, century, date2 = date_string:match ("((%d%d)%d%d)[%s%-–]+(%d%d)");
    date1, century, date2 = date_string:match ("((%d%d)%d%d)[%s%-–]+(%d%d)");
    Line 599: Line 606:
    result = 0;
    result = 0;
    end
    end
    else
    result = 0; -- no recognizable year in date
    end
    end
    return result;
    return result;
    end
    end


    return {dates = dates, year_date_check = year_date_check} -- return exported functions
     
    --[[-------------------------< 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
    }