User:Kxx/comments in local time.js

/*   COMMENTS IN LOCAL TIME Description: Changes UTC-based times and dates, such as those used in signatures, to be relative to local time. Documentation: Comments in Local Time Source: User:Gary King/comments in local time.js

(function(undefined) {   var window = this, document = window.document;    switch (window.mw.config.get('wgCanonicalNamespace')) {    case '':    case 'MediaWiki':    case 'Special':        return;    }    if (window.mw.config.get('wgAction') === 'history')        return;    var addLeadingZero = function(number) {            return number < 10 ? '0' + number : number;        },        convertMonthToNumber = {            January: 0, Jan: 0,            February: 1, Feb: 1,            March: 2, Mar: 2,            April: 3, Apr: 3,            May: 4,            June: 5, Jun: 5,            July: 6, Jul: 6,            August: 7, Aug: 7,            September: 8, Sep: 8,            October: 9, Oct: 9,            November: 10, Nov: 10,            December: 11, Dec: 11        },        convertNumberToMonth = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], Date = window.Date, Math = window.Math, parseInt = window.parseInt, pluralize = function(term, count) { return count === 1 ? term : term + 's'; },       search = /(\d\d):(\d\d), (\d{1,2}) ([A-Z][a-z]+) (\d{4}) \(UTC\)/g, today = new Date(new Date.toDateString), adjustTime = function(matches) { // set the date entered var time = new Date(Date.UTC(parseInt(matches[5]), convertMonthToNumber[matches[4]], parseInt(matches[3]), parseInt(matches[1]), parseInt(matches[2])));

// determine the time offset var utcOffset = today.getTimezoneOffset / -60; utcOffset = utcOffset >= 0 ? '+' + utcOffset : '−' + -utcOffset;

// set the date bits to output var year = time.getFullYear; var month = time.getMonth; var day = time.getDate; var hour = time.getHours; var minute = time.getMinutes;

// output am or pm depending on the date var ampm = hour <= 11 ? ' am' : ' pm'; if (hour > 12) hour -= 12; else if (hour === 0) hour = 12;

// return 'today', 'yesterday' or 'tomorrow' if that is the case var oldDate = new Date(year, month, day), date; switch (Math.round((oldDate.getTime - today.getTime) / 8.64e7)) { case -1: date = 'yesterday'; break; case 0: date = 'today'; break; case 1: date = 'tomorrow'; break; default: var newDate = new Date(today);

// calculate time difference from today var daysDiff = Math.round((newDate.getTime - oldDate.getTime) / 8.64e7);

var differenceWord, last = ''; if (daysDiff >= 0) { differenceWord = 'ago'; if (daysDiff <= 7) last = 'last '; } else { differenceWord = 'from now'; if (daysDiff > -7) last = 'this '; var tmpDate = newDate; newDate = oldDate; oldDate = tmpDate; }

var newYear = newDate.getFullYear, newMonth = newDate.getMonth, newDay = newDate.getDate; var oldTime = oldDate.getTime, oldYear = oldDate.getFullYear, oldMonth = oldDate.getMonth; var yearsAgo = newYear - oldYear; if (new Date(oldYear, newMonth, newDay).getTime < oldTime) --yearsAgo; var monthsAgo = ((newYear - yearsAgo) * 12 + newMonth) - (oldYear * 12 + oldMonth); if (new Date(newYear - yearsAgo, newMonth - monthsAgo, newDay).getTime < oldTime) --monthsAgo; var daysAgo = Math.round((new Date(newYear - yearsAgo, newMonth - monthsAgo, newDay).getTime - oldTime) / 8.64e7);

var descriptiveParts = []; if (yearsAgo > 0) descriptiveParts.push(yearsAgo + ' ' + pluralize('year', yearsAgo)); if (monthsAgo > 0) descriptiveParts.push(monthsAgo + ' ' + pluralize('month', monthsAgo)); if (daysAgo > 0) descriptiveParts.push(daysAgo + ' ' + pluralize('day', daysAgo));

var descriptiveDifference = ' (' + descriptiveParts.join(', ') + ' ' + differenceWord + ')'; var formattedDate = convertNumberToMonth[month] + ' ' + day + ', ' + year; var formattedDayOfTheWeek = ', ' + last + dayNames[time.getDay]; date = formattedDate + formattedDayOfTheWeek + descriptiveDifference; }

var finalTime = hour + ':' + addLeadingZero(minute) + ampm; var returnDate = finalTime + ', ' + date + ' (UTC' + utcOffset + ')';

return returnDate; },       replaceText = function(root) { var stack = [root], textNodes = []; do { for (var child = stack.pop.firstChild; child; child = child.nextSibling) if (child.nodeType === 1) stack.push(child); else if (child.nodeType === 3) textNodes.push(child); } while (stack.length !== 0);

for (var i = 0, length = textNodes.length; i < length; ++i) { var node = textNodes[i], value = node.textContent;

var match = search.exec(value); if (!match) continue;

var fragment = document.createDocumentFragment, lastIndex = 0;

do { fragment.appendChild(document.createTextNode(value.substring(lastIndex, match.index))); lastIndex = search.lastIndex; var span = document.createElement('span'); span.className = 'localcomments'; span.title = match[0]; span.textContent = adjustTime(match); fragment.appendChild(span); match = search.exec(value); } while (match);

fragment.appendChild(document.createTextNode(value.substr(lastIndex)));

node.parentNode.replaceChild(fragment, node); }       };

var topContainer = document.getElementById('wikiPreview'); if (!topContainer && window.mw.config.get('wgAction') === 'view') topContainer = document.getElementById('mw-content-text') || document.getElementById('bodyContent');

if (topContainer) replaceText(topContainer); });