User:AlanM1/comments in local time.js

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.
/* eslint-disable */
/**
 * COMMENTS IN LOCAL TIME
 *
 * Description:
 * Changes [[Coordinated Universal Time|UTC]]-based times and dates,
 * such as those used in signatures, to be relative to local time.
 *
 * Documentation:
 * [[Wikipedia:Comments in Local Time]]
 */
var CommentsInLocalTime, runScript;

CommentsInLocalTime = (function() {
  var LocalComments, language;

  function CommentsInLocalTime() {}

  language = '';

  LocalComments = {};

  CommentsInLocalTime.settings = function() {
    if (window.LocalComments !== null) {
      LocalComments = window.LocalComments;
    }

    /*
      Language

      LOCALIZING THIS SCRIPT
      To localize this script, change the terms below,
      to the RIGHT of the colons, to the correct term used in that language.

      For example, in the French language,

      'Today' : 'Today',

      would be

      'Today' : "Aujourd'hui",
     */
    return (LocalComments.language = {
      /* relative terms */
      Today: 'Today',
      Yesterday: 'Yesterday',
      Tomorrow: 'Tomorrow',
      last: 'last',
      this: 'this',

      /* days of the week */
      Sunday: 'Sunday',
      Monday: 'Monday',
      Tuesday: 'Tuesday',
      Wednesday: 'Wednesday',
      Thursday: 'Thursday',
      Friday: 'Friday',
      Saturday: 'Saturday',

      /* months of the year */
      January: 'January',
      February: 'February',
      March: 'March',
      April: 'April',
      May: 'May',
      June: 'June',
      July: 'July',
      August: 'August',
      September: 'September',
      October: 'October',
      November: 'November',
      December: 'December',

      /* difference words */
      ago: 'ago',
      'from now': 'from now',

      /* date phrases */
      year: 'year',
      years: 'years',
      month: 'month',
      months: 'months',
      day: 'day',
      days: 'days',
    });
  };

  /*
    APPLICATION
   */

  CommentsInLocalTime.init = function() {
    /*
      Settings
     */
//	console.debug("CommentsInLocalTime.init(): Called");
    var contentText, namespace, pageAction;
    this.settings();
    if (LocalComments.language === null) {
      return false;
    }
    language = this.setDefaultSetting('language', LocalComments.language);
    this.setDefaultSetting({
      dateDifference: true,
      dateFormat: 'dmy',
      dayOfWeek: true,
      dropDays: 0,
      dropMonths: 0,
      timeFirst: true,
      twentyFourHours: false,
      dropOffset: 1,				/* AlanM1 */
      diffLast: false				/* AlanM1 */
    });
//	console.debug("CommentsInLocalTime.init(): after setDefaultSetting");

    /*
      End Settings
     */
    if (
      mw.config.get('wgCanonicalNamespace') === '' ||
      mw.config.get('wgCanonicalNamespace') == 'MediaWiki' ||
      mw.config.get('wgCanonicalNamespace') == 'Special'
    )
      return;

    var disabled_urls = new Array('action=history'),
      unique_url = false,
      wikiPreview = new Array('action=edit', 'action=submit');
    for (var i = 0; i < disabled_urls.length; i++) {
      if (document.location.href.indexOf(disabled_urls[i]) != -1) return;
    }
//	console.debug("CommentsInLocalTime.init(): after disabled_urls loop");

    for (var j = 0; j < wikiPreview.length; j++) {
      if (document.location.href.indexOf(wikiPreview[j]) != -1)
        unique_url = 'wikiPreview';
    }
//	console.debug("CommentsInLocalTime.init(): after wikiPreview loop");

    var element_id = unique_url ? unique_url : 'bodyContent';
//	console.debug("CommentsInLocalTime.init(): element_id is " + element_id);
    contentText = document.getElementById(element_id);
    var sRet = this.replaceText(
      contentText,
      /(\d{1,2}):(\d{2}), (\d{1,2}) ([A-Z][a-z]+) (\d{4}) \(UTC\)/
    );
//	console.debug("CommentsInLocalTime.init(): returning '" + sRet + "'");
	return sRet;
  };

  CommentsInLocalTime.replaceText = function(node, search) {
    var after,
      afterMatch,
      before,
      beforeMatch,
      child,
      children,
      length,
      match,
      matches,
      parent,
      parentNodeName,
      position,
      span,
      timeArray,
      timestamp,
      value,
      _i,
      _len,
      _results;
    if (!node) {
      return false;
    }
    if (node.nodeType === 3) {
      parent = node.parentNode;
      parentNodeName = parent.nodeName;
      if (['CODE', 'PRE'].indexOf(parentNodeName) > -1) {
        return false;
      }
      value = node.nodeValue;
      matches = value.match(search);
      if (matches !== null) {
        match = matches[0];
        position = value.search(search);
        length = match.toString().length;
        beforeMatch = value.substring(0, position);
        afterMatch = value.substring(position + length);
        timeArray = this.adjustTime(match.toString(), search);
//console.log('timeArray: ' + timeArray + '\n');
        timestamp = timeArray[1] ? timeArray[1].getTime() : '';
        span = document.createElement('span');
        span.className = 'localcomments';
        span.style.fontSize = '95%';
        span.style.whiteSpace = 'nowrap';
        span.setAttribute('timestamp', timestamp);
        span.title = match;
        span.appendChild(document.createTextNode(timeArray[0]));
        parent = node.parentNode;
        parent.replaceChild(span, node);
        before = document.createElement('span');
        before.className = 'before-localcomments';
        before.appendChild(document.createTextNode(beforeMatch));
        after = document.createElement('span');
        after.className = 'after-localcomments';
        after.appendChild(document.createTextNode(afterMatch));
        parent.insertBefore(before, span);
        return parent.insertBefore(after, span.nextSibling);
      }
    } else {
      children = [];
      child = node.childNodes[0];
      while (child) {
        children.push(child);
        child = child.nextSibling;
      }
      _results = [];
      for (_i = 0, _len = children.length; _i < _len; _i++) {
        child = children[_i];
        _results.push(this.replaceText(child, search));
      }
      return _results;
    }
  };

  CommentsInLocalTime.getZoneLetter = function(loffset) {
	var lzoneLetter = 'J';
  	var lindex = loffset + 12;
//console.log('loffset: ' + loffset + ', lindex: ' + lindex + '\n');
 	if (lindex >= 0 && lindex <= 24) {
  		lzoneLetter = 'YXWVUTSRQPONZABCDEFGHIKLM'.substring(lindex, lindex + 1);
  	}
//console.log('lzoneLetter: ' + lzoneLetter + '\n');
  	return lzoneLetter;
  };

  CommentsInLocalTime.adjustTime = function(originalTimestamp, search) {
    var ampm,
      bIsNear,														/* AlanM1 */
      date,
      day,
      dayNames,
      dayOfTheWeek,
      descriptiveDifference,
      finalTime,
      formattedDate,
      formattedDayOfTheWeek,
      hour,
      last,
      minute,
      month,
      monthName,
      offsetString,													/* AlanM1 */
      oldDay,
      oldHour,
      oldMinute,
      oldMonth,
      oldYear,
      returnDate,
      time,
      today,
      tomorrow,
      utcOffset,
      year,
      yesterday,
      _ref,
      _ref1,
      nOffset;
    time = originalTimestamp.match(search);
    (_ref = [time[1], time[2], time[3], time[4], time[5]]),
      (oldHour = _ref[0]),
      (oldMinute = _ref[1]),
      (oldDay = _ref[2]),
      (oldMonth = _ref[3]),
      (oldYear = _ref[4]);
    today = new Date();
    yesterday = new Date();
    tomorrow = new Date();
    yesterday.setDate(yesterday.getDate() - 1);
    tomorrow.setDate(tomorrow.getDate() + 1);
    time = new Date();
    time.setUTCFullYear(oldYear, this.convertMonthToNumber(oldMonth), oldDay);
    time.setUTCHours(oldHour);
    time.setUTCMinutes(oldMinute);
    if (isNaN(time)) {
      return [originalTimestamp, ''];
    }
    nOffset = (-1 * time.getTimezoneOffset()) / 60;
    utcOffset = nOffset >= 0 ? '+' + nOffset : '−' + Math.abs(nOffset);
    year = time.getFullYear();
    month = this.addLeadingZero(time.getMonth() + 1);
    day = time.getDate();
    hour = parseInt(time.getHours());
    minute = this.addLeadingZero(time.getMinutes());
    ampm = '';
    if (LocalComments.twentyFourHours) {
      hour = this.addLeadingZero(hour);
    } else {
      ampm = hour <= 11 ? ' am' : ' pm';
      if (hour > 12) {
        hour -= 12;
      } else if (hour === 0) {
        hour = 12;
      }
    }
	bIsNear = true;													/* AlanM1 */
    if (
      year === today.getFullYear() &&
      month === this.addLeadingZero(today.getMonth() + 1) &&
      day === today.getDate()
    ) {
      date = language['Today'];
    } else if (
      year === yesterday.getFullYear() &&
      month === this.addLeadingZero(yesterday.getMonth() + 1) &&
      day === yesterday.getDate()
    ) {
      date = language['Yesterday'];
    } else if (
      year === tomorrow.getFullYear() &&
      month === this.addLeadingZero(tomorrow.getMonth() + 1) &&
      day === tomorrow.getDate()
    ) {
      date = language['Tomorrow'];
	} else {
	  bIsNear = false;												/* AlanM1 */
    }																/* AlanM1 */
    if ((!bIsNear) || (LocalComments.diffLast)) {					/* AlanM1 */
      dayNames = [
        language['Sunday'],
        language['Monday'],
        language['Tuesday'],
        language['Wednesday'],
        language['Thursday'],
        language['Friday'],
        language['Saturday'],
      ];
      dayOfTheWeek = dayNames[time.getDay()];
      descriptiveDifference = '';
      last = '';
/*    if (LocalComments.dateDifference) { */						/* AlanM1 */
      if (!bIsNear && LocalComments.dateDifference) {				/* AlanM1 */
        (_ref1 = this.createRelativeDate(today, time)),
          (descriptiveDifference = _ref1.descriptiveDifference),
          (last = _ref1.last);
      }
      formattedDate = '';
      monthName = this.convertNumberToMonth(time.getMonth());
      formattedDate = function() {
        switch (LocalComments.dateFormat.toLowerCase()) {
          case 'dmy':
            return day + ' ' + monthName + ' ' + year;
          case 'mdy':
            return monthName + ' ' + day + ', ' + year;
          default:
            return year + '-' + month + '-' + this.addLeadingZero(day);
        }
      }.call(this);
      formattedDayOfTheWeek = '';
      if (LocalComments.dayOfWeek) {
        formattedDayOfTheWeek = ', ' + last + dayOfTheWeek;
      }
      date = formattedDate + formattedDayOfTheWeek + descriptiveDifference;
    }
    finalTime = hour + ':' + minute + ampm;
//console.log('LocalComments.dropOffset, utcOffset: ' + LocalComments.dropOffset + ', ' + utcOffset + '\n');
/* AlanM1 { */
    if (LocalComments.dropOffset == 0) {
      offsetString = ''
    } else if (LocalComments.dropOffset == 1) {
	  offsetString = this.getZoneLetter(nOffset);
    } else {	// 2
      offsetString = ' (UTC' + utcOffset + ')';
    }
//console.log('offsetString: ' + offsetString + '\n');

/*
*	if (LocalComments.timeFirst) {
*     returnDate = finalTime + ', ' + date + ' (UTC' + utcOffset + ')';
*   } else {
*     returnDate = date + ', ' + finalTime + ' (UTC' + utcOffset + ')';
*   }
*/
//console.log('LocalComments.timeFirst, LocalComments.diffLast: ' + LocalComments.timeFirst + ', ' + LocalComments.diffLast + '\n');
    if (LocalComments.timeFirst) {
      returnDate = finalTime + ', ' + date + offsetString;
    } else {
      if (LocalComments.diffLast) {
	    returnDate = formattedDate + 'T' + finalTime + offsetString + formattedDayOfTheWeek + descriptiveDifference;
      } else {
        returnDate = date + ', ' + finalTime + offsetString;
      }
    }
//console.log('returnDate: ' + returnDate + '\n');
/* AlanM1 } */
    return [returnDate, time];
  };

  CommentsInLocalTime.createRelativeDate = function(today, time) {
    var daysAgo,
      descriptiveParts,
      differenceWord,
      fmtDays,
      fmtMonths,
      fmtYears,
      last,
      millisecondsAgo,
      monthsAgo,
      totalMonthsAgo,
      yearsAgo;
    millisecondsAgo = today.getTime() - time.getTime();
    daysAgo = Math.abs(Math.round(millisecondsAgo / 1000 / 60 / 60 / 24));
    differenceWord = '';
    last = '';
    if (millisecondsAgo >= 0) {
      differenceWord = language['ago'];
      if (daysAgo <= 7) {
        last = language['last'] + ' ';
      }
    } else {
      differenceWord = language['from now'];
      if (daysAgo <= 7) {
        last = language['this'] + ' ';
      }
    }
    monthsAgo = Math.floor((daysAgo / 365) * 12);
    totalMonthsAgo = monthsAgo;
    yearsAgo = Math.floor(monthsAgo / 12);
    if (monthsAgo < LocalComments.dropMonths) {
      yearsAgo = 0;
    } else if (LocalComments.dropMonths > 0) {
      monthsAgo = 0;
    } else {
      monthsAgo = monthsAgo - yearsAgo * 12;
    }
    if (daysAgo < LocalComments.dropDays) {
      monthsAgo = 0;
      yearsAgo = 0;
    } else if (LocalComments.dropDays > 0) {
      daysAgo = 0;
    } else {
      daysAgo = daysAgo - Math.floor((totalMonthsAgo * 365) / 12);
    }
    descriptiveParts = [];
    if (yearsAgo > 0) {
      fmtYears =
        yearsAgo +
        ' ' +
        this.pluralize(language['year'], yearsAgo, language['years']);
      descriptiveParts.push(fmtYears);
    }
    if (monthsAgo > 0) {
      fmtMonths =
        monthsAgo +
        ' ' +
        this.pluralize(language['month'], monthsAgo, language['months']);
      descriptiveParts.push(fmtMonths);
    }
    if (daysAgo > 0) {
      fmtDays =
        daysAgo +
        ' ' +
        this.pluralize(language['day'], daysAgo, language['days']);
      descriptiveParts.push(fmtDays);
    }
    return {
      descriptiveDifference:
        ' (' + descriptiveParts.join(', ') + ' ' + differenceWord + ')',
      last: last,
    };
  };

  /*
    HELPERS
   */

  CommentsInLocalTime.addLeadingZero = function(number) {
    if (number < 10) {
      number = '0' + number;
    }
    return number;
  };

  CommentsInLocalTime.convertMonthToNumber = function(month) {
    return new Date(month + ' 1, 2001').getMonth();
  };

  CommentsInLocalTime.convertNumberToMonth = function(number) {
    return [
      language['January'],
      language['February'],
      language['March'],
      language['April'],
      language['May'],
      language['June'],
      language['July'],
      language['August'],
      language['September'],
      language['October'],
      language['November'],
      language['December'],
    ][number];
  };

  CommentsInLocalTime.pluralize = function(term, count, plural) {
    if (plural === null) {
      plural = term + 's';
    }
    if (count === 1) {
      return term;
    } else {
      return plural;
    }
  };

  CommentsInLocalTime.setDefaultSetting = function() {
    var defaultSetting, name, settings;
    if (!arguments.length) {
      return false;
    }
    if (typeof arguments[0] === 'object') {
      settings = arguments[0];
      for (name in settings) {
        defaultSetting = settings[name];
        if (LocalComments[name] == null) {
          LocalComments[name] = defaultSetting;
        }
      }
      return settings;
    } else if (typeof arguments[0] === 'string') {
      name = arguments[0];
      defaultSetting = arguments[1];
      if (LocalComments[name] == null) {
        LocalComments[name] = defaultSetting;
      }
      return LocalComments[name];
    }
  };

  return CommentsInLocalTime;
})();

$(() => CommentsInLocalTime.init());