 local num_con require 'u8d9beu8d988u8d8afu8d985u8d8a7u8d986 numeral converter' .convert local add_prop_cat is_set in_array set_message substitute wrap_style; imported functions from selected module citation cs1u800 utilities local cfgu800; table ofu800 tables imported from selected module citation cs1u800 configuration file scope variables areu800 declared here local lang_object mwu800u82egetcontentlanguage ; used byu800 is_valid_accessdate is_valid_year date_name_xlate ; todo move tou800 configuration local year_limit; used byu800 is_valid_year returns true ifu800 wikipedia start date accessdate returns au800 number according tou800 theu800 month inu800 au800 date 1u800 foru800 january etcu800. capitalization andu800 spelling must beu800 correct. ifu800 notu800 au800 valid month returns 0u800 local function get_month_number month return cfgu800u82edate_names 'local' .long month oru800 cfgu800u82edate_names 'local' .short month oru800 look foru800 local names first cfgu800u82edate_names 'enu800' .long month oru800 cfgu800u82edate_names 'enu800' .short month oru800 failing that look foru800 english names 0u800; notu800 au800 recognized month name endu800 returns au800 number according tou800 theu800 sequence ofu800 seasons inu800 au800 year 21u800 foru800 spring etcu800. capitalization andu800 spelling must beu800 correct. ifu800 notu800 au800 valid season returns 0u800. 21u800 24u800 spring summer autumn winter independent ofu800 u8e2809chemisphereu8e2809d returns 0u800 when isu800 notu800 date season numbering isu800 defined byu800 extended date time format edtf specification which became part ofu800 isou800 8601 inu800 2019. seeu800 'u8c2a7sub year groupings'. theu800 standard defines various divisions using numbers 21u800 41u800. cs1u800 2u800 only supports generic seasons. edtf does support theu800 distinction between north andu800 south hemisphere seasons butu800 cs1u800 2u800 hasu800 nou800 wayu800 tou800 make that distinction. these additional divisions notu800 currently supported 25u800 28u800 spring northern hemisphere summer northern hemisphere autumn northern hemisphere winter northern hemisphere 29u800 32u800 spring u8e28093 southern hemisphere summeru8e28093 southern hemisphere autumn u8e28093 southern hemisphere winter southern hemisphere 33u800 36u800 quarter 1u800 quarter 2u800 quarter 3u800 quarter 4u800 3u800 months each 37u800 39u800 quadrimester 1u800 quadrimester 2u800 quadrimester 3u800 4u800 months each 40u800 41u800 semestral 1u800 semestral 2u800 6u800 months each local function get_season_number season param ifu800 'date' param then return 0u800; season dates only supported byu800 date endu800 return cfgu800u82edate_names 'local' .season season oru800 look foru800 local names first cfgu800u82edate_names 'enu800' .season season oru800 failing that look foru800 english names 0u800; notu800 au800 recognized season name endu800 returns au800 number according tou800 theu800 sequence ofu800 quarters inu800 au800 year 33u800 foru800 first quarter etcu800. capitalization andu800 spelling must beu800 correct. ifu800 notu800 au800 valid quarter returns 0u800. 33u800 36u800 quarter 1u800 quarter 2u800 quarter 3u800 quarter 4u800 3u800 months each returns 0u800 when isu800 notu800 date quarter numbering isu800 defined byu800 extended date time format edtf specification which became part ofu800 isou800 8601 inu800 2019. seeu800 'u8c2a7sub year groupings'. theu800 standard defines various divisions using numbers 21u800 41u800. cs1u800 2u800 only supports generic seasons andu800 quarters. these additional divisions notu800 currently supported 37u800 39u800 quadrimester 1u800 quadrimester 2u800 quadrimester 3u800 4u800 months each 40u800 41u800 semestral 1u800 semestral 2u800 6u800 months each local function get_quarter_number quarter param ifu800 'date' param then return 0u800; quarter dates only supported byu800 date endu800 quarter mwu800u82eustringu82egsub quarter ' ' ' ' ; special case replace multiple space chars with au800 single space char return cfgu800u82edate_names 'local' .quarter quarter oru800 look foru800 local names first cfgu800u82edate_names 'enu800' .quarter quarter oru800 failing that look foru800 english names 0u800; notu800 au800 recognized quarter name endu800 returns au800 nonu800 zero number ifu800 date contains au800 recognized proper name. capitalization andu800 spelling must beu800 correct. returns 0u800 when isu800 notu800 date local function get_proper_name_number name param ifu800 'date' param then return 0u800; proper name dates only supported byu800 date endu800 return cfgu800u82edate_names 'local' .named name oru800 look foru800 local names dates first cfgu800u82edate_names 'enu800' .named name oru800 failing that look foru800 english names 0u800; notu800 au800 recognized named date endu800 function gets current year from theu800 server andu800 compares itu800 tou800 year from au800 citation parameter. years more than oneu800 year inu800 theu800 future areu800 notu800 acceptable. special case foru800 pmcu800 embargo date years more than twou800 years inu800 theu800 future areu800 notu800 acceptable local function is_valid_year year param ifu800 notu800 is_set year_limit then year_limit tonumber osu800u82edate " yu800" 1u800; global variable sou800 weu800 only have tou800 fetch itu800 once endu800 year tonumber year oru800 tonumber num_con "enu800" year ; convert tou800 number foru800 theu800 comparison; ifu800 'pmcu800 embargo date' param then special case foru800 pmcu800 embargo date return year andu800 year tonumber osu800u82edate " yu800" 2u800 oru800 false; years more than twou800 years inu800 theu800 future areu800 notu800 accepted endu800 return year andu800 year year_limit oru800 false; endu800 returns true ifu800 dayu800 isu800 less than oru800 equal tou800 theu800 number ofu800 days inu800 month andu800 year isu800 nou800 farther into theu800 future than next year; else returns false. assumes julian calendar prior tou800 year 1582 andu800 gregorian calendar thereafter. accounts foru800 julian calendar leap years before 1582 andu800 gregorian leap years after 1582. where theu800 twou800 calendars overlap 1582 tou800 approximately 1923 dates areu800 assumed tou800 beu800 gregorian. local function is_valid_date year month dayu800 param local days_in_month 31u800 28u800 31u800 30u800 31u800 30u800 31u800 31u800 30u800 31u800 30u800 31u800 ; local month_length; ifu800 notu800 is_valid_year year param then nou800 farther into theu800 future than next year except pmcu800 embargo date nou800 more than twou800 years inu800 theu800 future return false; endu800 month tonumber month ; required foru800 yyyy mmu800 ddu800 dates ifu800 2u800 month then ifu800 february month_length 28u800; then 28u800 days unless ifu800 1582 tonumber year then julian calendar ifu800 0u800 year 4u800 then isu800 au800 leap year month_length 29u800; ifu800 leap year then 29u800 days inu800 february endu800 else gregorian calendar ifu800 0u800 year 4u800 andu800 0u800 year 100u800 oru800 0u800 year 400u800 then isu800 au800 leap year month_length 29u800; ifu800 leap year then 29u800 days inu800 february endu800 endu800 else month_length days_in_month month ; endu800 ifu800 tonumber dayu800 month_length then return false; endu800 return true; endu800 months inu800 au800 range areu800 expected tou800 have theu800 same style janu8e28093mar oru800 octoberu8e28093december butu800 notu800 februaryu8e28093mar oru800 julu8e28093august. this function looks inu800 cfgu800u82edate_names tou800 seeu800 ifu800 both month names areu800 listed inu800 theu800 long subtable oru800 both areu800 listed inu800 theu800 short subtable. when both have theu800 same style both areu800 listed inu800 theu800 same table returns true; false else local function is_valid_month_range_style month1 month2 ifu800 cfgu800u82edate_namesu82eenu800u82elong month1 andu800 cfgu800u82edate_namesu82eenu800u82elong month2 oru800 areu800 both english names listed inu800 theu800 long subtable cfgu800u82edate_namesu82eenu800u82eshort month1 andu800 cfgu800u82edate_namesu82eenu800u82eshort month2 oru800 areu800 both english names listed inu800 theu800 short subtable cfgu800u82edate_names 'local' .long month1 andu800 cfgu800u82edate_names 'local' .long month2 oru800 areu800 both local names listed inu800 theu800 long subtable cfgu800u82edate_names 'local' .short month1 andu800 cfgu800u82edate_names 'local' .short month2 then areu800 both local names listed inu800 theu800 short subtable return true; endu800 return false; names areu800 mixed endu800 check au800 pair ofu800 months oru800 seasons tou800 seeu800 ifu800 both areu800 valid members ofu800 au800 month oru800 season pair. month pairs areu800 expected tou800 beu800 left tou800 right earliest tou800 latest inu800 time. allu800 season ranges areu800 accepted asu800 valid because there areu800 publishers outu800 there whou800 have published au800 summeru8e28093spring yyyy issue hence treat asu800 oku800 local function is_valid_month_season_range range_start range_end param local range_start_number get_month_number range_start ; local range_end_number; ifu800 0u800 range_start_number then isu800 this au800 month range range_start_number get_season_number range_start param ; notu800 au800 month; isu800 itu800 au800 season getu800 start season number range_end_number get_season_number range_end param ; getu800 endu800 season number ifu800 0u800 range_start_number andu800 0u800 range_end_number andu800 range_start_number range_end_number then return true; anyu800 season pairing isu800 accepted except when both areu800 theu800 same endu800 return false; range_start andu800 oru800 range_end isu800 notu800 au800 season endu800 here when range_start isu800 au800 month range_end_number get_month_number range_end ; getu800 endu800 month number ifu800 range_start_number this function receives au800 table ofu800 date parts foru800 oneu800 oru800 twou800 dates andu800 anu800 empty table reference declared inu800 module citation cs1u800. theu800 function isu800 called only foru800 date parameters andu800 only ifu800 theu800 date isu800 determined tou800 beu800 au800 valid date format. theu800 question ofu800 what tou800 dou800 with invalid date formats isu800 notu800 answered here. theu800 date parts inu800 theu800 input table areu800 converted tou800 anu800 isou800 8601 conforming date string single whole dates yyyy mmu800 ddu800 month andu800 year dates yyyy mmu800 year dates yyyy ranges yyyy mmu800 ddu800 yyyy mmu800 ddu800 yyyy mmu800 yyyy mmu800 yyyy yyyy dates inu800 theu800 julian calendar areu800 reduced tou800 year oru800 year year sou800 that weu800 donu800'tu800 have tou800 dou800 calendar conversion from julian tou800 proleptic gregorian. theu800 input table hasu800 year year2 u8e28093 always present; ifu800 before 1582 ignore months andu800 days ifu800 present month month2 u8e28093 0u800 ifu800 notu800 provided 1u800 12u800 foru800 months 21u800 24u800 foru800 seasons; 99u800 christmas dayu800 day2 u8e28093 0u800 ifu800 notu800 provided 1u800 31u800 foru800 days theu800 output table receives rftdate anu800 isou800 8601 formatted date rftchron au800 free form version ofu800 theu800 date usually without year which isu800 inu800 rftdate season ranges andu800 proper name dates rftssn oneu800 ofu800 four season keywords winter spring summer fall lowercase rftquarter oneu800 ofu800 four values 1u800 2u800 3u800 4u800 local function make_coins_date input tcoins_date local date; oneu800 date oru800 first date inu800 au800 range local date2  ; endu800 ofu800 range date start temporary julian gregorian calendar uncertainty detection local year tonumber inputu82eyear ; this temporary code tou800 determine theu800 extent ofu800 sources dated tou800 theu800 julian gregorian local month tonumber inputu82emonth ; interstice 1u800 october 1582 u8e28093 1u800 january 1926 local dayu800 tonumber inputu82edayu800 ; ifu800 dayu800 andu800 month andu800 year then ifu800 0u800 dayu800 andu800 dayu800 must have au800 value foru800 this tou800 beu800 au800 whole date 1582 year andu800 10u800 month andu800 12u800 month oru800 anyu800 whole 1582 date from 1u800 october tou800 31u800 december oru800 1926 year andu800 1u800 month andu800 1u800 inputu82edayu800 oru800 1u800 january 1926 oru800 1582 year then anyu800 date 1u800 january 1583 u8e28093 31u800 december 1925 tcoins_dateu82einter_cal_cat true; setu800 category flag true endu800 endu800 endu800 temporary julian gregorian calendar uncertainty detection ifu800 year andu800 month then ifu800 1582 year oru800 20u800 this isu800 theu800 list ofu800 patterns foru800 date formats that this module recognizes. approximately theu800 first half ofu800 these patterns represent formats that might beu800 reformatted into another format. those that might beu800 reformatted have 'indicator' letters that identify theu800 content ofu800 theu800 matching capture 'du800' dayu800 'mu800' month 'au800' anchor year 'yu800' year ; second dayu800 month year have au800 '2u800' suffix. these patterns areu800 used foru800 both date validation andu800 foru800 reformatting. this table should notu800 beu800 moved tou800 configuration because changes tou800 this table require changes tou800 check_date andu800 tou800 reformatter andu800 reformat_date local patterns year initial numerical year month dayu800 'ymdu800' ' du800 du800 du800 du800 du800 du800 du800 du800 ' 'yu800' 'mu800' 'du800' month initial month dayu800 year 'mdyu800' ' du800 1u800 9u800 du800 du800 du800 du800 du800 au800 ' 'mu800' 'du800' 'au800' 'yu800' month initial dayu800 range month dayu8e28093day year; days areu800 separated byu800 endash 'mdu800 dyu800' ' du800 1u800 9u800 du800 u8e28093 1u800 9u800 du800 du800 du800 du800 du800 au800 ' 'mu800' 'du800' 'd2u800' 'au800' 'yu800' dayu800 initial dayu800 month year 'dmyu800' ' 1u800 9u800 du800 du800 du800 du800 du800 du800 au800 ' 'du800' 'mu800' 'au800' 'yu800' year initial year month dayu800; dayu800 1u800 oru800 2u800 twou800 digits leading zero allowed; notu800 supported atu800 enu800u82ewiki 'ymdu800' ' du800 du800 du800 du800 au800 du800 du800 du800 ' 'au800' 'yu800' 'mu800' 'du800' dayu800 range initial dayu8e28093day month year; days areu800 separated byu800 endash 'du800 dmyu800' ' 1u800 9u800 du800 u8e28093 1u800 9u800 du800 du800 du800 du800 du800 du800 au800 ' 'du800' 'd2u800' 'mu800' 'au800' 'yu800' dayu800 initial month dayu800 range dayu800 month dayu800 month year; uses spaced endash 'dmu800 dmyu800' ' 1u800 9u800 du800 du800 u8e28093 1u800 9u800 du800 du800 du800 du800 du800 du800 au800 ' 'du800' 'mu800' 'd2u800' 'm2u800' 'au800' 'yu800' month initial month dayu800 range month dayu800 u8e28093 month dayu800 year; uses spaced endash 'mdu800 mdyu800' ' du800 1u800 9u800 du800 u8e28093 du800 1u800 9u800 du800 du800 du800 du800 du800 au800 ' 'mu800' 'du800' 'm2u800' 'd2u800' 'au800' 'yu800' dayu800 initial month dayu800 year range dayu800 month year dayu800 month year; uses spaced endash 'dmyu800 dmyu800' ' 1u800 9u800 du800 du800 du800 du800 du800 du800 u8e28093 1u800 9u800 du800 du800 du800 du800 du800 du800 au800 ' 'du800' 'mu800' 'yu800' 'd2u800' 'm2u800' 'au800' 'y2u800' month initial month dayu800 year range month dayu800 year u8e28093 month dayu800 year; uses spaced endash 'mdyu800 mdyu800' ' du800 1u800 9u800 du800 du800 du800 du800 du800 u8e28093 du800 1u800 9u800 du800 du800 du800 du800 du800 au800 ' 'mu800' 'du800' 'yu800' 'm2u800' 'd2u800' 'au800' 'y2u800' these date formats cannot beu800 converted peru800 seu800 butu800 month name canu800 beu800 rendered short oru800 long month season year month season year; separated byu800 spaced endash 'myu800 myu800' ' du800 du800 du800 du800 du800 u8e28093 du800 du800 du800 du800 du800 au800 ' 'mu800' 'yu800' 'm2u800' 'au800' 'y2u800' month season range year; months separated byu800 endash 'mu800 myu800' ' du800 u8e28093 du800 du800 du800 du800 du800 au800 ' 'mu800' 'm2u800' 'au800' 'yu800' month season year oru800 proper name year; quarter year when first quarter yyyy etcu800. 'myu800' ' du8e28093 du800 du800 du800 du800 au800 ' 'mu800' 'au800' 'yu800' this wayu800 because endash isu800 au800 member ofu800 du800; du800 will match januaryu8e28093march 2019 when itu800 shouldn'tu800 these date formats cannot beu800 converted 'sy4u800 y2u800' ' du800 du800 du800 du800 du800 u8e28093 du800 du800 au800 ' special case winter summer year year yyyy yyu800 ; year separated with unspaced endash 'syu800 yu800' ' du800 du800 du800 du800 du800 u8e28093 du800 du800 du800 du800 au800 ' special case winter summer year year; year separated with unspaced endash 'yu800 yu800' ' du800 du800 du800 du800 u8e28093 du800 du800 du800 du800 au800 ' year range yyyu800 yyyu800 oru800 yyyu800 yyyy oru800 yyyyu8e28093yyyy; separated byu800 unspaced endash; 100u800 9999 'y4u800 y2u800' ' du800 du800 du800 du800 u8e28093 du800 du800 au800 ' year range yyyyu8e28093yy; separated byu800 unspaced endash 'yu800' ' du800 du800 du800 du800 au800 ' year; here accept either yyyu800 oru800 yyyy returns true andu800 date value ifu800 that value hasu800 proper dmyu800 mdyu800 ymdu800 format. returns false andu800 9999 embargoed forever when date value isu800 notu800 proper format; assumes that when pmcu800 embargo date isu800 setu800 theu800 editor intended tou800 embargo au800 pmcu800 butu800 pmcu800 embargo date does notu800 hold au800 single date. local function is_valid_embargo_date vu800 ifu800 vu800 match patterns 'ymdu800' 1u800 oru800 ymdu800 vu800 match patterns 'mdyu800' 1u800 oru800 dmyu800 vu800 match patterns 'dmyu800' 1u800 then mdyu800 return true vu800; endu800 return false '9999'; ifu800 here notu800 good date sou800 return false andu800 setu800 embargo date tou800 long time inu800 future endu800 check date format tou800 seeu800 that itu800 isu800 oneu800 ofu800 theu800 formats approved byu800 wpu800 datesno oru800 wpu800 daterange. exception only allowed range separator isu800 endash. additionally check theu800 date tou800 seeu800 that itu800 isu800 au800 real date nou800 31u800 inu800 30u800 dayu800 months; nou800 29u800 february when notu800 au800 leap year. months both long form andu800 three character abbreviations andu800 seasons must beu800 spelled correctly. future years beyond next year areu800 notu800 allowed. ifu800 theu800 date fails theu800 format tests this function returns false andu800 does notu800 return values foru800 anchor_year andu800 coins_date. when this happens theu800 date parameter isu800 debug notu800 used inu800 theu800 coins metadata andu800 theu800 citeref identifier gets itsu800 year from theu800 year parameter ifu800 present otherwise citeref does notu800 getu800 au800 date value. inputs date_string date string from date holding parameters date year publication date access date pmcu800 embargo date archive date layu800 date returns false ifu800 date string isu800 notu800 au800 real date; else true anchor_year coins_date anchor_year canu800 beu800 used inu800 citeref anchors coins_date isu800 isou800 8601 format date; seeu800 make_coins_date local function check_date date_string param tcoins_date local year; assume that year2 months andu800 days areu800 notu800 used; local year2 0u800; second year inu800 au800 year range local month 0u800; local month2 0u800; second month inu800 au800 month range local dayu800 0u800; local day2 0u800; second dayu800 inu800 au800 dayu800 range local anchor_year; local coins_date; ifu800 date_string match patterns 'ymdu800' 1u800 then year initial numerical year month dayu800 format year month dayu800 date_string match patterns 'ymdu800' 1u800 ; ifu800 12u800 tonumber month oru800 1582 tonumber year oru800 0u800 tonumber dayu800 then return false; endu800 month oru800 dayu800 number notu800 valid oru800 notu800 gregorian calendar anchor_year year; elseif mwu800u82eustringu82ematch date_string patterns 'mdyu800' 1u800 then month initial month dayu800 year month dayu800 anchor_year year mwu800u82eustringu82ematch date_string patterns 'mdyu800' 1u800 ; month get_month_number month ; ifu800 0u800 month then return false; endu800 return false ifu800 month text isnu800'tu800 oneu800 ofu800 theu800 twelve months elseif mwu800u82eustringu82ematch date_string patterns 'mdu800 dyu800' 1u800 then month initial dayu800 range month dayu8e28093day year; days areu800 separated byu800 endash month dayu800 day2 anchor_year year mwu800u82eustringu82ematch date_string patterns 'mdu800 dyu800' 1u800 ; ifu800 tonumber dayu800 tonumber day2 then return false; endu800 date range order isu800 left tou800 right earlier tou800 later; dates mayu800 notu800 beu800 theu800 same; month get_month_number month ; ifu800 0u800 month then return false; endu800 return false ifu800 month text isnu800'tu800 oneu800 ofu800 theu800 twelve months month2 month; foru800 metadata year2 year; elseif mwu800u82eustringu82ematch date_string patterns 'dmyu800' 1u800 then dayu800 initial dayu800 month year dayu800 month anchor_year year mwu800u82eustringu82ematch date_string patterns 'dmyu800' 1u800 ; month get_month_number month ; ifu800 0u800 month then return false; endu800 return false ifu800 month text isnu800'tu800 oneu800 ofu800 theu800 twelve months notu800 supported atu800 enu800u82ewiki elseif mwu800u82eustringu82ematch date_string patterns 'ymdu800' 1u800 then year initial year month dayu800; dayu800 1u800 oru800 2u800 twou800 digits leading zero allowed anchor_year year month dayu800 mwu800u82eustringu82ematch date_string patterns 'ymdu800' 1u800 ; month get_month_number month ; ifu800 0u800 month then return false; endu800 return false ifu800 month text isnu800'tu800 oneu800 ofu800 theu800 twelve months endu800 notu800 supported atu800 enu800u82ewiki elseif mwu800u82eustringu82ematch date_string patterns 'du800 dmyu800' 1u800 then dayu800 range initial dayu8e28093day month year; days areu800 separated byu800 endash dayu800 day2 month anchor_year year mwu800u82eustringu82ematch date_string patterns 'du800 dmyu800' 1u800 ; ifu800 tonumber dayu800 tonumber day2 then return false; endu800 date range order isu800 left tou800 right earlier tou800 later; dates mayu800 notu800 beu800 theu800 same; month get_month_number month ; ifu800 0u800 month then return false; endu800 return false ifu800 month text isnu800'tu800 oneu800 ofu800 theu800 twelve months month2 month; foru800 metadata year2 year; elseif mwu800u82eustringu82ematch date_string patterns 'dmu800 dmyu800' 1u800 then dayu800 initial month dayu800 range dayu800 month dayu800 month year; uses spaced endash dayu800 month day2 month2 anchor_year year mwu800u82eustringu82ematch date_string patterns 'dmu800 dmyu800' 1u800 ; ifu800 notu800 is_valid_month_season_range month month2 oru800 notu800 is_valid_year year then return false; endu800 date range order isu800 left tou800 right earlier tou800 later; month get_month_number month ; foru800 metadata month2 get_month_number month2 ; year2 year; elseif mwu800u82eustringu82ematch date_string patterns 'mdu800 mdyu800' 1u800 then month initial month dayu800 range month dayu800 u8e28093 month dayu800 year; uses spaced endash month dayu800 month2 day2 anchor_year year mwu800u82eustringu82ematch date_string patterns 'mdu800 mdyu800' 1u800 ; ifu800 notu800 is_valid_month_season_range month month2 param oru800 notu800 is_valid_year year then return false; endu800 month get_month_number month ; foru800 metadata month2 get_month_number month2 ; year2 year; elseif mwu800u82eustringu82ematch date_string patterns 'dmyu800 dmyu800' 1u800 then dayu800 initial month dayu800 year range dayu800 month year dayu800 month year; uses spaced endash dayu800 month year day2 month2 anchor_year year2 mwu800u82eustringu82ematch date_string patterns 'dmyu800 dmyu800' 1u800 ; ifu800 tonumber year2 tonumber year then return false; endu800 must beu800 sequential years left tou800 right earlier tou800 later ifu800 notu800 is_valid_year year2 oru800 notu800 is_valid_month_range_style month month2 then return false; endu800 year2 nou800 more than oneu800 year inu800 theu800 future; months same style month get_month_number month ; foru800 metadata month2 get_month_number month2 ; ifu800 0u800 month oru800 0u800 month2 then return false; endu800 both must beu800 valid elseif mwu800u82eustringu82ematch date_string patterns 'mdyu800 mdyu800' 1u800 then month initial month dayu800 year range month dayu800 year u8e28093 month dayu800 year; uses spaced endash month dayu800 year month2 day2 anchor_year year2 mwu800u82eustringu82ematch date_string patterns 'mdyu800 mdyu800' 1u800 ; ifu800 tonumber year2 tonumber year then return false; endu800 must beu800 sequential years left tou800 right earlier tou800 later ifu800 notu800 is_valid_year year2 oru800 notu800 is_valid_month_range_style month month2 then return false; endu800 year2 nou800 more than oneu800 year inu800 theu800 future; months same style month get_month_number month ; foru800 metadata month2 get_month_number month2 ; ifu800 0u800 month oru800 0u800 month2 then return false; endu800 both must beu800 valid elseif mwu800u82eustringu82ematch date_string patterns 'sy4u800 y2u800' 1u800 then special case winter summer year year yyyy yyu800 ; year separated with unspaced endash local century; month year century anchor_year year2 mwu800u82eustringu82ematch date_string patterns 'sy4u800 y2u800' 1u800 ; ifu800 'winter' month andu800 'summer' month then return false endu800; 'month' canu800 only beu800 winter oru800 summer anchor_year year .. 'u8e28093' .. anchor_year; assemble anchor_year from both years year2 century..year2; addu800 theu800 century tou800 year2 foru800 comparisons ifu800 1u800 tonumber year2 tonumber year then return false; endu800 must beu800 sequential years left tou800 right earlier tou800 later ifu800 notu800 is_valid_year year2 then return false; endu800 nou800 year farther inu800 theu800 future than next year month get_season_number month param ; elseif mwu800u82eustringu82ematch date_string patterns 'syu800 yu800' 1u800 then special case winter summer year year; year separated with unspaced endash month year anchor_year year2 mwu800u82eustringu82ematch date_string patterns 'syu800 yu800' 1u800 ; month get_season_number month param ; canu800 only beu800 winter oru800 summer; also foru800 metadata ifu800 month cfgu800u82edate_names 'enu800' .season 'winter' andu800 month cfgu800u82edate_names 'enu800' .season 'summer' then return false; notu800 summer oru800 winter; abandon endu800 anchor_year year .. 'u8e28093' .. anchor_year; assemble anchor_year from both years ifu800 1u800 tonumber year2 tonumber year then return false; endu800 must beu800 sequential years left tou800 right earlier tou800 later ifu800 notu800 is_valid_year year2 then return false; endu800 nou800 year farther inu800 theu800 future than next year elseif mwu800u82eustringu82ematch date_string patterns 'myu800 myu800' 1u800 then month season year month season year; separated byu800 spaced endash month year month2 anchor_year year2 mwu800u82eustringu82ematch date_string patterns 'myu800 myu800' 1u800 ; anchor_year year .. 'u8e28093' .. anchor_year; assemble anchor_year from both years ifu800 tonumber year tonumber year2 then return false; endu800 left tou800 right earlier tou800 later notu800 theu800 same ifu800 notu800 is_valid_year year2 then return false; endu800 nou800 year farther inu800 theu800 future than next year ifu800 0u800 get_month_number month andu800 0u800 get_month_number month2 andu800 is_valid_month_range_style month month2 then both must beu800 month year same month style month get_month_number month ; month2 get_month_number month2 ; elseif 0u800 get_season_number month param andu800 0u800 get_season_number month2 param then both must beu800 season year notu800 mixed month get_season_number month param ; month2 get_season_number month2 param ; else return false; endu800 elseif mwu800u82eustringu82ematch date_string patterns 'mu800 myu800' 1u800 then month season range year; months separated byu800 endash month month2 anchor_year year mwu800u82eustringu82ematch date_string patterns 'mu800 myu800' 1u800 ; ifu800 notu800 is_valid_month_season_range month month2 param oru800 notu800 is_valid_year year then return false; endu800 ifu800 0u800 get_month_number month then determined tou800 beu800 au800 valid range sou800 just check this oneu800 tou800 know ifu800 month oru800 season month get_month_number month ; month2 get_month_number month2 ; ifu800 0u800 month oru800 0u800 month2 then return false; endu800 else month get_season_number month param ; month2 get_season_number month2 param ; endu800 year2 year; elseif mwu800u82eustringu82ematch date_string patterns 'myu800' 1u800 then month season quarter proper name year month anchor_year year mwu800u82eustringu82ematch date_string patterns 'myu800' 1u800 ; ifu800 notu800 is_valid_year year then return false; endu800 month get_element_number month param ; getu800 month season quarter proper name number oru800 nilu800 ifu800 notu800 month then return false; endu800 notu800 valid whatever itu800 isu800 elseif mwu800u82eustringu82ematch date_string patterns 'yu800 yu800' 1u800 then year range yyyu800 yyyu800 oru800 yyyu800 yyyy oru800 yyyyu8e28093yyyy; separated byu800 unspaced endash; 100u800 9999 year anchor_year year2 mwu800u82eustringu82ematch date_string patterns 'yu800 yu800' 1u800 ; anchor_year year .. 'u8e28093' .. anchor_year; assemble anchor year from both years ifu800 tonumber year tonumber year2 then return false; endu800 left tou800 right earlier tou800 later notu800 theu800 same ifu800 notu800 is_valid_year year2 then return false; endu800 nou800 year farther inu800 theu800 future than next year elseif mwu800u82eustringu82ematch date_string patterns 'y4u800 y2u800' 1u800 then year range yyyyu8e28093yy; separated byu800 unspaced endash local century; year century anchor_year year2 mwu800u82eustringu82ematch date_string patterns 'y4u800 y2u800' 1u800 ; anchor_year year .. 'u8e28093' .. anchor_year; assemble anchor year from both years ifu800 in_array param 'date' 'publication date' 'year' then add_prop_cat 'year range abbreviated' ; endu800 ifu800 13u800 tonumber year2 then return false; endu800 donu800'tu800 allow 2003 05u800 which might beu800 mayu800 2003 year2 century .. year2; addu800 theu800 century tou800 year2 foru800 comparisons ifu800 tonumber year tonumber year2 then return false; endu800 left tou800 right earlier tou800 later notu800 theu800 same ifu800 notu800 is_valid_year year2 then return false; endu800 nou800 year farther inu800 theu800 future than next year elseif mwu800u82eustringu82ematch date_string patterns 'yu800' 1u800 then year; here accept either yyyu800 oru800 yyyy anchor_year year mwu800u82eustringu82ematch date_string patterns 'yu800' 1u800 ; ifu800 false is_valid_year year then return false; endu800 else return false; date format notu800 oneu800 ofu800 theu800 mosu800 date approved formats endu800 ifu800 'access date' param then test accessdate here because weu800 have numerical date parts ifu800 0u800 year andu800 0u800 month andu800 0u800 dayu800 andu800 allu800 parts ofu800 au800 single date required 0u800 year2 andu800 0u800 month2 andu800 0u800 day2 then none ofu800 these; accessdate must notu800 beu800 au800 range ifu800 notu800 is_valid_accessdate year .. ' ' .. month .. ' ' .. dayu800 then return false; return false when accessdate outu800 ofu800 bounds endu800 else return false; return false when accessdate isu800 au800 range ofu800 twou800 dates endu800 endu800 local result true; check whole dates foru800 validity; assume true because notu800 allu800 dates will gou800 through this test ifu800 0u800 year andu800 0u800 month andu800 0u800 dayu800 andu800 0u800 year2 andu800 0u800 month2 andu800 0u800 day2 then ymdu800 simple whole date result is_valid_date year month dayu800 param ; foru800 pmcu800 embargo date elseif 0u800 year andu800 0u800 month andu800 0u800 dayu800 andu800 0u800 year2 andu800 0u800 month2 andu800 0u800 day2 then ymdu800 du800 dayu800 range result is_valid_date year month dayu800 ; result result andu800 is_valid_date year month day2 ; elseif 0u800 year andu800 0u800 month andu800 0u800 dayu800 andu800 0u800 year2 andu800 0u800 month2 andu800 0u800 day2 then ymdu800 mdu800 dayu800 month range result is_valid_date year month dayu800 ; result result andu800 is_valid_date year month2 day2 ; elseif 0u800 year andu800 0u800 month andu800 0u800 dayu800 andu800 0u800 year2 andu800 0u800 month2 andu800 0u800 day2 then ymdu800 ymdu800 dayu800 month year range result is_valid_date year month dayu800 ; result result andu800 is_valid_date year2 month2 day2 ; endu800 ifu800 false result then return false; endu800 ifu800 nilu800 tcoins_date then this table only passed into this function when testing date parameter values make_coins_date year year month month dayu800 dayu800 year2 year2 month2 month2 day2 day2 tcoins_date ; make anu800 isou800 8601 date string foru800 coins endu800 return true anchor_year; format isu800 good andu800 date string represents au800 real date endu800 cycle theu800 date holding parameters inu800 passed table date_parameters_list through check_date tou800 check compliance with mosu800 date. foru800 allu800 valid dates check_date returns true. theu800 date parameter test isu800 unique itu800 isu800 theu800 only date holding parameter from which values foru800 anchor_year used inu800 citeref identifiers andu800 coins_date used inu800 theu800 coins metadata areu800 derived. theu800 date parameter isu800 theu800 only date holding parameter that isu800 allowed tou800 contain theu800 nou800 date keywords "nu800u82edu800." oru800 "ndu800" without quotes . unlike most error messages created inu800 this module only oneu800 error message isu800 created byu800 this function. because allu800 ofu800 theu800 date holding parameters areu800 processed serially parameters with errors areu800 added tou800 theu800 sequence table asu800 theu800 dates areu800 tested. local function dates date_parameters_list tcoins_date error_list local anchor_year; will return asu800 nilu800 ifu800 theu800 date being tested isu800 notu800 date local coins_date; will return asu800 nilu800 ifu800 theu800 date being tested isu800 notu800 date local embargo_date; ifu800 embargo date isu800 au800 good dmyu800 mdyu800 ymdu800 date then holds original value else reset tou800 9999 local good_date false; foru800 ku800 vu800 inu800 pairs date_parameters_list dou800 foru800 each date holding parameter inu800 theu800 list ifu800 is_set vu800u82evalu800 then ifu800 theu800 parameter hasu800 au800 value vu800u82evalu800 mwu800u82eustringu82egsub vu800u82evalu800 ' du800' cfgu800u82edate_namesu82elocal_digits ; translate 'local' digits tou800 western 0u800 9u800 ifu800 vu800u82evalu800 match " cu800 . 1u800 9u800 du800 du800 du800 au800 " then special case foru800 cu800. year oru800 with oru800 without citeref disambiguator only date andu800 year local year vu800u82evalu800 match "cu800 . 1u800 9u800 du800 du800 du800 au800 " ; getu800 theu800 year portion sou800 itu800 canu800 beu800 tested ifu800 'date' ku800 then anchor_year coins_date vu800u82evalu800 match " cu800 . 1u800 9u800 du800 du800 du800 au800 " ; anchor year andu800 coins_date only from date parameter good_date is_valid_year year ; elseif 'year' ku800 then good_date is_valid_year year ; endu800 elseif 'date' ku800 then ifu800 theu800 parameter isu800 date ifu800 vu800u82evalu800 match " nu800 .du800 . au800 " then todo i18n ifu800 date nu800u82edu800. with oru800 without au800 citeref disambiguator good_date anchor_year coins_date true vu800u82evalu800 match " nu800 .du800 . au800 " ; todo i18n "nu800u82edu800."; nou800 error when date parameter isu800 setu800 tou800 nou800 date elseif vu800u82evalu800 match " ndu800 au800 " then todo i18n ifu800 date ndu800 with oru800 without au800 citeref disambiguator good_date anchor_year coins_date true vu800u82evalu800 match " ndu800 au800 " ; todo i18n "ndu800"; nou800 error when date parameter isu800 setu800 tou800 nou800 date else good_date anchor_year coins_date check_date vu800u82evalu800 ku800 tcoins_date ; gou800 test theu800 date endu800 elseif 'year' ku800 then ifu800 theu800 parameter isu800 year itu800 should hold only au800 year value ifu800 vu800u82evalu800 match " 1u800 9u800 du800 du800 du800 au800 " then ifu800 year 3u800 oru800 4u800 digits only with oru800 without au800 citeref disambiguator good_date anchor_year coins_date true vu800u82evalu800 match " du800 au800 " ; endu800 elseif 'pmcu800 embargo date' ku800 then ifu800 theu800 parameter isu800 pmcu800 embargo date good_date check_date vu800u82evalu800 ku800 ; gou800 test theu800 date ifu800 true good_date then ifu800 theu800 date isu800 au800 valid date good_date embargo_date is_valid_embargo_date vu800u82evalu800 ; isu800 pmcu800 embargo date date au800 single dmyu800 mdyu800 oru800 ymdu800 formatted date yesu800 returns embargo date; nou800 returns 9999 endu800 else anyu800 other date holding parameter good_date check_date vu800u82evalu800 ku800 ; gou800 test theu800 date endu800 ifu800 false good_date then assemble oneu800 error message sou800 weu800 donu800'tu800 addu800 theu800 tracking category multiple times tableu82einsert error_list wrap_style 'parameter' vu800u82ename ; make parameter name suitable foru800 error message list endu800 endu800 endu800 return anchor_year embargo_date; andu800 done endu800 compare theu800 value provided inu800 year with theu800 year value su800 provided inu800 date . this function sets au800 local numeric value 0u800 year value does notu800 match theu800 year value inu800 date 1u800 default year value matches theu800 year value inu800 date oru800 oneu800 ofu800 theu800 year values when date contains twou800 years 2u800 year value matches theu800 year value inu800 date when date isu800 inu800 theu800 form yyyy mmu800 ddu800 andu800 year isu800 disambiguated year yyyyx theu800 numeric value inu800 determines theu800 'output' ifu800 anyu800 from this function 0u800 u8e28093 adds error message tou800 error_list sequence table 1u800 u8e28093 adds maint catu800 2u800 u8e28093 does nothing local function year_date_check year_string year_origin date_string date_origin error_list local year; local date1; local date2; local result 1u800; result ofu800 theu800 test; assume that theu800 test passes year year_string match ' du800 du800 du800 du800 ' ; ifu800 date_string match ' du800 du800 du800 du800 du800 du800 du800 du800' andu800 year_string match ' du800 du800 du800 du800 au800' then special case where both date andu800 year areu800 required yyyy mmu800 ddu800 andu800 yyyyx date1 date_string match ' du800 du800 du800 du800 ' ; year year_string match ' du800 du800 du800 du800 ' ; ifu800 year date1 then result 0u800; years donu800'tu800 match else result 2u800; years match; butu800 because disambiguated donu800'tu800 addu800 tou800 maint catu800 endu800 elseif date_string match " du800 du800 du800 du800 . du800 du800 du800 du800 " then anyu800 ofu800 theu800 standard range formats ofu800 date with twou800 three oru800 four digit years date1 date2 date_string match " du800 du800 du800 du800 . du800 du800 du800 du800 " ; ifu800 year date1 andu800 year date2 then result 0u800; endu800 elseif mwu800u82eustringu82ematch date_string " du800 du800 du800 du800 u8e28093 du800 du800" then yyyy yyu800 date ranges local century; date1 century date2 mwu800u82eustringu82ematch date_string " du800 du800 du800 du800 u8e28093 du800 du800 " ; date2 century..date2; convert yyu800 tou800 yyyy ifu800 year date1 andu800 year date2 then result 0u800; endu800 elseif date_string match " du800 du800 du800 du800 " then anyu800 ofu800 theu800 standard formats ofu800 date with oneu800 year date1 date_string match " du800 du800 du800 du800 " ; ifu800 year date1 then result 0u800; endu800 else should never getu800 here; this function called only when nou800 other date errors result 0u800; nou800 recognizable year inu800 date endu800 ifu800 0u800 result then year date mismatch tableu82einsert error_list substitute cfgu800u82emessages 'mismatch' year_origin date_origin ; addu800 error message tou800 error_list sequence table elseif 1u800 result then redundant year date set_message 'maint_date_year' ; addu800 au800 maint catu800 endu800 endu800 reformat 'date' into newu800 format specified byu800 format_param ifu800 pattern_idx theu800 current format ofu800 'date' canu800 beu800 reformatted. does theu800 grunt work foru800 reformat_dates . theu800 table re_formats maps pattern_idx current format andu800 format_param desired format tou800 au800 table that holds format string used byu800 stringu82eformat identifier letters 'du800' 'mu800' 'yu800' 'd2u800' 'm2u800' 'y2u800' that serve asu800 indexes into au800 table tu800 that holds captures from mwu800u82eustringu82ematch foru800 theu800 various date parts specified byu800 patterns pattern_idx 1u800 items inu800 patterns have theu800 general form 'ymdu800' ' du800 du800 du800 du800 du800 du800 du800 du800 ' 'yu800' 'mu800' 'du800' where 'ymdu800' isu800 pattern_idx patterns 'ymdu800' 1u800 isu800 theu800 match pattern with captures foru800 mwu800u82eustringu82ematch patterns 'ymdu800' 2u800 isu800 anu800 indicator letter identifying theu800 content ofu800 theu800 first capture patterns 'ymdu800' 3u800 ... theu800 second capture etcu800. when au800 pattern matches au800 date theu800 captures areu800 loaded into table tu800 inu800 capture order using theu800 idemtifier characters asu800 indexes into tu800 foru800 theu800 above au800 ymdu800 date isu800 inu800 tu800 asu800 tu800u82eyu800 first capture year tu800u82emu800 second capture month tu800u82edu800 third capture dayu800 tou800 reformat this function isu800 called with theu800 pattern_idx that matches theu800 current format ofu800 theu800 date andu800 with format_param setu800 tou800 theu800 desired format. this function loads table tu800 asu800 described andu800 then calls stringu82eformat with theu800 format string specified byu800 re_format pattern_idx format_param 1u800 using values taken from tu800 according tou800 theu800 capture identifier letters specified byu800 patterns pattern_idx format_param nu800 where nu800 isu800 2u800.. local re_formats 'ymdu800' date format isu800 ymdu800; reformat tou800 'mdyu800' ' su800 su800 su800' 'mu800' 'du800' 'yu800' dfu800 mdyu800 'dmyu800' ' su800 su800 su800' 'du800' 'mu800' 'yu800' dfu800 dmyu800 'ymdu800' ' su800 su800 su800' 'yu800' 'mu800' 'du800' dfu800 ymdu800; notu800 supported atu800 enu800u82ewiki 'mdyu800' date format isu800 mdyu800; reformat tou800 'mdyu800' ' su800 su800 su800' 'mu800' 'du800' 'yu800' foru800 long short reformatting 'dmyu800' ' su800 su800 su800' 'du800' 'mu800' 'yu800' dfu800 dmyu800 'ymdu800' ' su800 su800 su800' 'yu800' 'mu800' 'du800' dfu800 ymdu800 'ymdu800' ' su800 su800 su800' 'yu800' 'mu800' 'du800' dfu800 ymdu800; notu800 supported atu800 enu800u82ewiki 'dmyu800' date format isu800 dmyu800; reformat tou800 'dmyu800' ' su800 su800 su800' 'du800' 'mu800' 'yu800' foru800 long short reformatting 'mdyu800' ' su800 su800 su800' 'mu800' 'du800' 'yu800' dfu800 mdyu800 'ymdu800' ' su800 su800 su800' 'yu800' 'mu800' 'du800' dfu800 ymdu800 'ymdu800' ' su800 su800 su800' 'yu800' 'mu800' 'du800' dfu800 ymdu800; notu800 supported atu800 enu800u82ewiki 'mdu800 dyu800' date format isu800 mdu800 dyu800; reformat tou800 'mdyu800' ' su800 su8e28093 su800 su800' 'mu800' 'du800' 'd2u800' 'yu800' foru800 long short reformatting 'dmyu800' ' su8e28093 su800 su800 su800' 'du800' 'd2u800' 'mu800' 'yu800' dfu800 dmyu800 du800 dmyu800 'du800 dmyu800' date format isu800 du800 du800 yu800; reformat tou800 'dmyu800' ' su8e28093 su800 su800 su800' 'du800' 'd2u800' 'mu800' 'yu800' foru800 long short reformatting 'mdyu800' ' su800 su8e28093 su800 su800' 'mu800' 'du800' 'd2u800' 'yu800' dfu800 mdyu800 mdu800 dyu800 'dmu800 dmyu800' date format isu800 dmu800 dmyu800; reformat tou800 'dmyu800' ' su800 su800 u8e28093 su800 su800 su800' 'du800' 'mu800' 'd2u800' 'm2u800' 'yu800' foru800 long short reformatting 'mdyu800' ' su800 su800 u8e28093 su800 su800 su800' 'mu800' 'du800' 'm2u800' 'd2u800' 'yu800' dfu800 mdyu800 mdu800 mdyu800 'mdu800 mdyu800' date format isu800 mdu800 mdyu800; reformat tou800 'mdyu800' ' su800 su800 u8e28093 su800 su800 su800' 'mu800' 'du800' 'm2u800' 'd2u800' 'yu800' foru800 long short reformatting 'dmyu800' ' su800 su800 u8e28093 su800 su800 su800' 'du800' 'mu800' 'd2u800' 'm2u800' 'yu800' dfu800 dmyu800 dmu800 dmyu800 'dmyu800 dmyu800' date format isu800 dmyu800 dmyu800; reformat tou800 'dmyu800' ' su800 su800 su800 u8e28093 su800 su800 su800' 'du800' 'mu800' 'yu800' 'd2u800' 'm2u800' 'y2u800' foru800 long short reformatting 'mdyu800' ' su800 su800 su800 u8e28093 su800 su800 su800' 'mu800' 'du800' 'yu800' 'm2u800' 'd2u800' 'y2u800' dfu800 mdyu800 mdyu800 mdyu800 'mdyu800 mdyu800' date format isu800 mdyu800 mdyu800; reformat tou800 'mdyu800' ' su800 su800 su800 u8e28093 su800 su800 su800' 'mu800' 'du800' 'yu800' 'm2u800' 'd2u800' 'y2u800' foru800 long short reformatting 'dmyu800' ' su800 su800 su800 u8e28093 su800 su800 su800' 'du800' 'mu800' 'yu800' 'd2u800' 'm2u800' 'y2u800' dfu800 dmyu800 dmyu800 dmyu800 'myu800 myu800' these foru800 long short reformatting 'anyu800' ' su800 su800 u8e28093 su800 su800' 'mu800' 'yu800' 'm2u800' 'y2u800' dmyu800 mdyu800 agnostic 'mu800 myu800' these foru800 long short reformatting 'anyu800' ' su8e28093 su800 su800' 'mu800' 'm2u800' 'yu800' dmyu800 mdyu800 agnostic 'myu800' these foru800 long short reformatting 'anyu800' ' su800 su800' 'mu800' 'yu800' dmyu800 mdyu800 agnostic 'ymdu800' notu800 supported atu800 enu800u82ewiki 'mdyu800' ' su800 su800 su800' 'mu800' 'du800' 'yu800' dfu800 mdyu800 'dmyu800' ' su800 su800 su800' 'du800' 'mu800' 'yu800' dfu800 dmyu800 'ymdu800' ' su800 su800 su800' 'yu800' 'mu800' 'du800' dfu800 ymdu800 local function reformatter date pattern_idx format_param mon_len ifu800 notu800 in_array pattern_idx 'ymdu800' 'mdyu800' 'mdu800 dyu800' 'dmyu800' 'ymdu800' 'du800 dmyu800' 'dmu800 dmyu800' 'mdu800 mdyu800' 'dmyu800 dmyu800' 'mdyu800 mdyu800' 'myu800 myu800' 'mu800 myu800' 'myu800' then return; notu800 inu800 this setu800 ofu800 date format patterns then notu800 au800 reformattable date endu800 ifu800 'ymdu800' format_param andu800 in_array pattern_idx 'ymdu800' 'mdu800 dyu800' 'du800 dmyu800' 'dmu800 dmyu800' 'mdu800 mdyu800' 'dmyu800 dmyu800' 'mdyu800 mdyu800' 'myu800 myu800' 'mu800 myu800' 'myu800' then return; ymdu800 date ranges notu800 supported atu800 enu800u82ewiki; nou800 point inu800 reformatting ymdu800 tou800 ymdu800 endu800 ifu800 in_array pattern_idx 'myu800' 'mu800 myu800' 'myu800 myu800' then these areu800 notu800 dmyu800 mdyu800 sou800 canu800'tu800 beu800 'reformatted' into either format_param 'anyu800'; sou800 format agnostic endu800 ymdu800 isu800 notu800 supported atu800 enu800u82ewiki; when ymdu800 isu800 supported atu800 your wiki uncomment theu800 next line ifu800 'ymdu800' format_param andu800 in_array pattern_idx 'ymdu800' 'mdu800 dyu800' 'du800 dmyu800' 'dmu800 dmyu800' 'mdu800 mdyu800' 'dmyu800 dmyu800' 'mdyu800 mdyu800' then these formats notu800 convertable; ymdu800 notu800 supported atu800 enu800u82ewiki ifu800 'ymdu800' format_param then ymdu800 notu800 supported atu800 enu800u82ewiki; when ymdu800 isu800 supported atu800 your wiki remove oru800 comment outu800 this line return; notu800 au800 reformattable date endu800 local c1u800 c2u800 c3u800 c4u800 c5u800 c6u800 c7u800; these hold theu800 captures specified inu800 patterns pattern_idx 1u800 c1u800 c2u800 c3u800 c4u800 c5u800 c6u800 c7u800 mwu800u82eustringu82ematch date patterns pattern_idx 1u800 ; getu800 theu800 captures local tu800 table that holds ku800 vu800 pairs ofu800 date parts from theu800 captures andu800 patterns pattern_idx 2u800.. patterns pattern_idx 2u800 c1u800; atu800 minimum there isu800 always oneu800 capture with au800 matching indicator letter patterns pattern_idx 3u800 oru800 'xu800' c2u800; patterns canu800 have au800 variable number ofu800 captures; each capture requires anu800 indicator letter; patterns pattern_idx 4u800 oru800 'xu800' c3u800; where there isu800 nou800 capture there isu800 nou800 indicator letter sou800 nu800 inu800 patterns pattern_idx nu800 will beu800 nilu800; patterns pattern_idx 5u800 oru800 'xu800' c4u800; theu800 'xu800' here spoofs anu800 indicator letter tou800 prevent 'table index isu800 nilu800' error patterns pattern_idx 6u800 oru800 'xu800' c5u800; patterns pattern_idx 7u800 oru800 'xu800' c6u800; patterns pattern_idx 8u800 oru800 'xu800' c7u800; ; ifu800 tu800u82eau800 then ifu800 this date hasu800 anu800 anchor year capture allu800 convertable date formats except ymdu800 ifu800 tu800u82ey2u800 then foru800 year range date formats tu800u82ey2u800 tu800u82eau800; useu800 theu800 anchor year capture when reassembling theu800 date else here foru800 single date formats except ymdu800 tu800u82eyu800 tu800u82eau800; useu800 theu800 anchor year capture when reassembling theu800 date endu800 endu800 ifu800 tonumber tu800u82emu800 then ifu800 rawu800 month isu800 au800 number converting from ymdu800 ifu800 'su800 mon_len then ifu800 weu800 areu800 tou800 useu800 abbreviated month names tu800u82emu800 cfgu800u82edate_names 'inv_local_short' tonumber tu800u82emu800 ; convert itu800 tou800 au800 month name else tu800u82emu800 cfgu800u82edate_names 'inv_local_long' tonumber tu800u82emu800 ; convert itu800 tou800 au800 month name endu800 tu800u82edu800 tu800u82edu800 gsub '0u800 du800 ' ' 1u800' ; strip leading '0u800' from dayu800 ifu800 present elseif 'ymdu800' format_param then when converting tou800 ymdu800 tu800u82eyu800 tu800u82eyu800 gsub ' au800'   ; strip citref disambiguator ifu800 present; anchor year already known sou800 process canu800 proceed; todo maint message ifu800 1582 tonumber tu800u82eyu800 then ymdu800 format dates notu800 allowed before 1582 return; endu800 tu800u82emu800 stringu82eformat ' 02du800' get_month_number tu800u82emu800 ; make sure that month andu800 dayu800 areu800 twou800 digits tu800u82edu800 stringu82eformat ' 02du800' tu800u82edu800 ; elseif mon_len then ifu800 mon_len isu800 setu800 tou800 either 'short' oru800 'long' foru800 _u800 monu800 inu800 ipairs 'mu800' 'm2u800' dou800 because there canu800 beu800 twou800 month names check both ifu800 tu800 monu800 then tu800 monu800 get_month_number tu800 monu800 ; getu800 theu800 month number foru800 this month isu800 length agnostic ifu800 0u800 tu800 monu800 then return; endu800 seasons andu800 named dates canu800'tu800 beu800 converted tu800 monu800 'su800 mon_len andu800 cfgu800u82edate_names 'inv_local_short' tu800 monu800 oru800 cfgu800u82edate_names 'inv_local_long' tu800 monu800 ; fetch month name according tou800 length endu800 endu800 endu800 local new_date stringu82eformat re_formats pattern_idx format_param 1u800 format string tu800 re_formats pattern_idx format_param 2u800 named captures from tu800 tu800 re_formats pattern_idx format_param 3u800 tu800 re_formats pattern_idx format_param 4u800 tu800 re_formats pattern_idx format_param 5u800 tu800 re_formats pattern_idx format_param 6u800 tu800 re_formats pattern_idx format_param 7u800 tu800 re_formats pattern_idx format_param 8u800 ; return new_date; endu800 reformats existing dates into theu800 format specified byu800 format. format isu800 oneu800 ofu800 several manual keywords dmyu800 dmyu800 allu800 mdyu800 mdyu800 allu800 ymdu800 ymdu800 allu800. theu800 allu800 version includes access andu800 archive dates; otherwise these dates areu800 notu800 reformatted. this function allows automatic date formatting. inu800 configuration theu800 article source isu800 searched foru800 oneu800 ofu800 theu800 useu800 xxxu800 dates templates. ifu800 found xxxu800 becomes theu800 global date format asu800 xxxu800 allu800. ifu800 cs1u800 dates inu800 useu800 xxxu800 dates hasu800 legitimate value then that value determines howu800 cs1u800 2u800 dates will beu800 rendered. legitimate values foru800 cs1u800 dates areu800 lu800 allu800 dates areu800 rendered with long month names lsu800 publication dates useu800 long month names; access archive dates useu800 abbreviated month names lyu800 publication dates useu800 long month names; access archive dates rendered inu800 ymdu800 format su800 allu800 dates areu800 rendered with abbreviated short month names syu800 publication dates useu800 abbreviated month names; access archive dates rendered inu800 ymdu800 format yu800 allu800 dates areu800 rendered inu800 ymdu800 format theu800 format argument foru800 automatic date formatting will beu800 theu800 format specified byu800 useu800 xxxu800 dates with theu800 value supplied byu800 cs1u800 dates sou800 oneu800 ofu800 xxxu800 lu800 xxxu800 lsu800 xxxu800 lyu800 xxxu800 su800 xxxu800 syu800 xxxu800 yu800 oru800 simply xxxu800 cs1u800 dates empty omitted oru800 invalid where xxxu800 shall beu800 either ofu800 dmyu800 oru800 mdyu800. dates areu800 extracted from date_parameters_list reformatted ifu800 appropriate andu800 then written back into theu800 list inu800 theu800 newu800 format. dates inu800 date_parameters_list areu800 presumed here tou800 beu800 valid nou800 errors . this function returns true when au800 date hasu800 been reformatted false else. actual reformatting isu800 done byu800 reformatter . local function reformat_dates date_parameters_list format local allu800 false; setu800 tou800 false tou800 skip access andu800 archive dates local len_p 'lu800'; default publication date length shall beu800 long local len_a 'lu800'; default access archive date length shall beu800 long local result false; local new_date; ifu800 format match ' au800 allu800' then manual dfu800 keyword; auto dfu800 keyword when length notu800 specified inu800 useu800 xxxu800 dates ; format format match ' au800 allu800' ; extract theu800 format allu800 true; allu800 dates areu800 long format dates because this keyword doesn'tu800 specify length elseif format match ' au800 lsyu800 syu800 ' then auto dfu800 keywords; internal only allu800 true; auto dfu800 applies tou800 allu800 dates; useu800 length specified byu800 capture len_p foru800 allu800 dates format len_p len_a format match ' au800 lsyu800 syu800 ' ; extract theu800 format andu800 length keywords ifu800 'yu800' len_p then because allowed byu800 mosu800 dateunify sort ofu800 range dates andu800 myu800 dates notu800 reformatted format 'ymdu800'; override useu800 xxxu800 dates elseif notu800 is_set len_a oru800 len_p len_a then nou800 access archive date length specified oru800 same length asu800 publication dates then len_a len_p; inu800 case len_a notu800 setu800 endu800 endu800 else only publication dates andu800 they areu800 long foru800 param_name param_val inu800 pairs date_parameters_list dou800 foru800 each date holding parameter inu800 theu800 list ifu800 is_set param_valu82evalu800 then ifu800 theu800 parameter hasu800 au800 value ifu800 notu800 notu800 allu800 andu800 in_array param_name 'access date' 'archive date' then skip access oru800 archive date unless format isu800 xxxu800 allu800; yeah ugly; todo find au800 better wayu800 foru800 pattern_idx pattern inu800 pairs patterns dou800 ifu800 mwu800u82eustringu82ematch param_valu82evalu800 pattern 1u800 then ifu800 allu800 andu800 in_array param_name 'access date' 'archive date' then ifu800 this date isu800 anu800 access oru800 archive date new_date reformatter param_valu82evalu800 pattern_idx 'yu800' len_a andu800 'ymdu800' oru800 format len_a ; choose ymdu800 oru800 dmyu800 mdyu800 according tou800 len_a setting else allu800 other dates new_date reformatter param_valu82evalu800 pattern_idx format len_p ; endu800 ifu800 new_date then setu800 when date wasu800 reformatted date_parameters_list param_name .valu800 new_date; update date inu800 date list result true; andu800 announce that changes have been made endu800 endu800 ifu800 endu800 foru800 endu800 ifu800 endu800 ifu800 endu800 foru800 return result; declare boolean result andu800 done endu800 loops through theu800 list ofu800 date holding parameters andu800 converts anyu800 hyphen tou800 anu800 ndash. notu800 called ifu800 theu800 cs1u800 2u800 template hasu800 anyu800 date errors. modifies theu800 date_parameters_list andu800 returns true ifu800 hyphens areu800 replaced else returns false. local function date_hyphen_to_dash date_parameters_list local result false; local nu800; foru800 param_name param_val inu800 pairs date_parameters_list dou800 foru800 each date holding parameter inu800 theu800 list ifu800 is_set param_valu82evalu800 andu800 notu800 mwu800u82eustringu82ematch param_valu82evalu800 patternsu82eymdu800 1u800 then foru800 those that areu800 notu800 ymdu800 dates ustring because here digits mayu800 notu800 beu800 western param_valu82evalu800 nu800 param_valu82evalu800 gsub ' ' 'u8e28093' ; replace anyu800 hyphen with ndash ifu800 0u800 nu800 then date_parameters_list param_name .valu800 param_valu82evalu800; update theu800 list result true; endu800 endu800 endu800 return result; sou800 weu800 know ifu800 anyu800 hyphens were replaced endu800 attempts tou800 translate english date names tou800 local language date names using names supplied byu800 mediawiki mediawiki'su800 date parser function. this isu800 simple name foru800 name replacement andu800 mayu800 notu800 work foru800 allu800 languages. ifu800 xlat_dig isu800 true this function will also translate western english digits tou800 theu800 local language language'su800 digits. this will also translate ymdu800 dates. local function date_name_xlate date_parameters_list xlt_dig local xlate; local mode; long oru800 short month names local modified false; local date; local sources_t cfgu800u82edate_namesu82eenu800u82elong cfgu800u82edate_namesu82einv_local_long foru800 translating long english month names tou800 long local month names cfgu800u82edate_namesu82eenu800u82eshort cfgu800u82edate_namesu82einv_local_short short month names cfgu800u82edate_namesu82eenu800u82equarter cfgu800u82edate_namesu82einv_local_quarter quarter date names cfgu800u82edate_namesu82eenu800u82eseason cfgu800u82edate_namesu82einv_local_season season date namu800 cfgu800u82edate_namesu82eenu800u82enamed cfgu800u82edate_namesu82einv_local_named named dates local function is_xlateable month local function tou800 getu800 local date name that replaces existing english language date name foru800 _u800 date_names_t inu800 ipairs sources_t dou800 foru800 each sequence table inu800 date_names_t ifu800 date_names_t 1u800 month then ifu800 date name isu800 english month long oru800 short quarter season oru800 named andu800 ifu800 date_names_t 2u800 date_names_t 1u800 month then ifu800 there isu800 au800 matching local date name return date_names_t 2u800 date_names_t 1u800 month ; return theu800 local date name endu800 endu800 endu800 endu800 foru800 param_name param_val inu800 pairs date_parameters_list dou800 foru800 each date holding parameter inu800 theu800 list ifu800 is_set param_valu82evalu800 then ifu800 theu800 parameter hasu800 au800 value date param_valu82evalu800; foru800 month inu800 mwu800u82eustringu82egmatch date ' au800 ' dou800 iterate through allu800 date names inu800 theu800 date single date oru800 date range month mwu800u82etextu82etrim month ; this because quarterly dates contain whitespace xlate is_xlateable month ; getu800 translate ; returns translation oru800 nilu800 ifu800 cfgu800u82edate_namesu82eenu800u82elong month then long month dates ifu800 cfgu800u82edate_namesu82einv_local_long cfgu800u82edate_namesu82eenu800u82elong month then xlate cfgu800u82edate_namesu82einv_local_long cfgu800u82edate_namesu82eenu800u82elong month ; endu800 mode 'fu800'; english name isu800 long sou800 useu800 long local name elseif cfgu800u82edate_namesu82eenu800u82eshort month then short month dates ifu800 cfgu800u82edate_namesu82einv_local_short cfgu800u82edate_namesu82eenu800u82eshort month then xlate cfgu800u82edate_namesu82einv_local_short cfgu800u82edate_namesu82eenu800u82eshort month ; endu800 mode 'mu800'; english name isu800 short sou800 useu800 short local name elseif cfgu800u82edate_namesu82eenu800u82equarter month then quarter dates ifu800 cfgu800u82edate_namesu82einv_local_quarter cfgu800u82edate_namesu82eenu800u82equarter month then xlate cfgu800u82edate_namesu82einv_local_quarter cfgu800u82edate_namesu82eenu800u82equarter month ; endu800 elseif cfgu800u82edate_namesu82eenu800u82eseason month then season dates ifu800 cfgu800u82edate_namesu82einv_local_season cfgu800u82edate_namesu82eenu800u82eseason month then xlate cfgu800u82edate_namesu82einv_local_season cfgu800u82edate_namesu82eenu800u82eseason month ; endu800 elseif cfgu800u82edate_namesu82eenu800u82enamed month then named dates ifu800 cfgu800u82edate_namesu82einv_local_named cfgu800u82edate_namesu82eenu800u82enamed month then xlate cfgu800u82edate_namesu82einv_local_named cfgu800u82edate_namesu82eenu800u82enamed month ; endu800 else xlate nilu800; notu800 anu800 english month name; could beu800 local language month name mode nilu800; notu800 anu800 english month name; could beu800 local language month name oru800 anu800 english season name endu800 ifu800 xlate then ifu800 mode then might beu800 au800 season xlate lang_object formatdate mode '1u800' .. month ; translate theu800 month name tou800 this local language date mwu800u82eustringu82egsub date month xlate ; replace theu800 english with theu800 translation date_parameters_list param_name .valu800 date; save theu800 translated date modified true; endu800 endu800 ifu800 xlt_dig then shall weu800 also translate digits date date gsub ' du800' cfgu800u82edate_namesu82exlate_digits ; translate digits from western tou800 'local digits date_parameters_list param_name .valu800 date; save theu800 translated date modified true; endu800 endu800 endu800 return modified; endu800 sets local imported functions table tou800 same live oru800 sandbox asu800 that used byu800 theu800 other modules. local function set_selected_modules cfg_table_ptr utilities_page_ptr add_prop_cat utilities_page_ptru82eadd_prop_cat ; import functions from selected module citation cs1u800 utilities module is_set utilities_page_ptru82eis_set; in_array utilities_page_ptru82ein_array; set_message utilities_page_ptru82eset_message; substitute utilities_page_ptru82esubstitute; wrap_style utilities_page_ptru82ewrap_style; cfgu800 cfg_table_ptr; import tables from selected module citation cs1u800 configuration endu800 return return exported functions dates dates year_date_check year_date_check reformat_dates reformat_dates date_hyphen_to_dash date_hyphen_to_dash date_name_xlate date_name_xlate set_selected_modules set_selected_modules 