Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// [[User:Quarl/date_canonicalize.js]] - canonicalizes date WikiLinks

//  Example: July 17, 1982 becomes [[1982-07-17]]

// requires: wikipage.js, util.js, addlilink.js, datetime.js

// quarl 2006-01-31 initial version

//<pre><nowiki>

datez = new autoedit(
    'datez',
    'DateZ',
    'ca-datez',
    'Canonicalize dates',
    'Date canonicalization');

// Return a string for a regexp that matches possibly wiki-linked dates in
// various date formats.  This is a monster regexp, the hardest part of this
// script!
datez.buildRegExp = function() {

    var groupIfNeccessary = function(s) {
        // I don't know a good way to check against e.g. "(foo)|(bar)"; for now just be conservative in adding grouping
        if (s.match(/\|/) /*&& !s.match(/^\(/) */ ) {
            return '(?:' + s + ')';
        } else {
            return s;
        }
    }

    var joinRE = function() {
        // desplice arguments
        var args = Array.concat.apply(Array, arguments).map(groupIfNeccessary);

        return '(?:' + args.join('|') + ')';
    }

    var linked = function(s) {
        return '\\[\\[ *'+s+' *\\]\\]';
    }

    var maybelinked = function(s) {
        return joinRE(linked(s), s);
    }

    var abbrevMonth = function(s) {
        return s.substr(0,3);
    }

    var word = function(s) {
        return '\\b' + s + '\\b';
    }

    var year4 = word('[012][0-9][0-9][0-9]');
    var year42 = word(joinRE(year4, '[890][0-9]'));
    var month = word(joinRE('0?[1-9]', '1[012]'));
    // monthnames is in datetime.js
    var monthS = word(joinRE(monthnames, monthnames.map(abbrevMonth)));
    var day = word('[0123]?[0-9](?:\'?st|nd|th)?');

    var delimz = '[ ,/-]+';

    var all = joinRE(
        // YYYY-MM-DD formats
        linked( year4 + '-' + month + '-' + day ),
        maybelinked(year4)+'-'+maybelinked(month+'-'+day),
        maybelinked(year4)+'/'+month+'/'+day,
        maybelinked(year4)+'\\.'+month+'\\.'+day,
        year4 + ' ' + month + ' ' + day,

        maybelinked(year4 + delimz + monthS + delimz + day),

        // MM-DD-YYYY formats
        month + '-' + day + '-' + year4,
        month + '/' + day + '/' + year42,

        linked(monthS + delimz + day + delimz + year42),
        maybelinked(monthS + delimz + day) + delimz + maybelinked(year42),
        linked(monthS) + delimz + linked(day) + delimz + '(?:of\s*)?' + linked(year42),

        // DD-MM-YYYY formats: only support monthS, because it's ambiguous
        // otherwise
        linked( day + delimz + monthS + delimz + year4 ),
        maybelinked(day + delimz + monthS) + delimz + maybelinked(year4)
        );
    return new RegExp(all, 'i');
}

datez.replaceRegExp = function(d, m) {
    s = m[0];
    s = s.replace(/[\[\]]/g, '');
    s = s.replace(/[-.]/g, '/'); // Date only understands '/' as delimiter
    var d = new Date(s); // parses date string

    if (!d.getFullYear()) {
        // couldn't parse
        return null;
    }

    return '[[' + datestampUTCISO(d) + ']]';
}

datez._load = function() {
    datez.addTab();
}

addOnloadHook(datez._load);

//</nowiki></pre>