Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump.
This code will be executed when previewing this page.
This code will be executed when previewing this page.
This user script seems to have a documentation page at User:Mfield/Scripts/RelativeTimestamps.
//Script to add human relative times after wiki timestamps - assumes UTC
function updateRecentHumanDiffs(){ //updates an timestamps of less than an hour every minute
$('.mf-reltime.mf-recent').each(function(){
let oldmin = parseInt($(this).text().replace(/[^0-9]/g,''));
if (oldmin==59){
$(this).html(' (1 hr. ago)').removeClass('mf-recent');
return;
}
$(this).html(` (${oldmin+1} min. ago)`);
});
}
$(function(){
//only run in view or history modes
if (!['view', 'history'].includes(mw.config.values.wgAction)){
return false;
}
var style = $(`<style>
.mf-reltime {
font-size: 0.8em;
display: inline-block;
margin-left: 5px;
min-width: 75px;
position: relative;
top: -1px;
}
.mw-enhanced-rc .mf-reltime {
margin-left: 0px;
margin-right: 5px;
font-family: sans-serif;
}
.mf-recent {
font-weight: bold;
}
.mw-enhanced-rc .mf-reltime.mf-recent {
font-weight: normal;
}
</style>`);
$('html > head').append(style);
var timestampUpdateTimer;
Date.prototype.humanDiff = function () {
const diff_ms = this - new Date();
const diff_m = diff_ms / 60000;
const timeScalars = [60, 24, 7, 4.345, 12];
const timeUnits = ['minute', 'hour', 'day', 'week', 'month', 'year'];
let timeScalarIndex = 0, scaledTime = diff_m;
while (Math.abs(scaledTime) > timeScalars[timeScalarIndex]) {
scaledTime /= timeScalars[timeScalarIndex++];
}
const rtf = new Intl.RelativeTimeFormat("en", { style: "short" });
return rtf.format(scaledTime.toFixed(0), timeUnits[timeScalarIndex]);
};
function formatDateFromVariousWikiDateFormats(unknown){
let offset = mw.user.options.get( 'timecorrection' ).split( '|' )[ 1 ]/60;
let offset_text = (offset < 0 ? '-' : '+')+String(Math.abs(offset)).padStart(2,0)+':00';
if (unknown.indexOf('UTC')>-1) offset_text = '+00:00';
let rgx = new RegExp(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d/)
if (unknown.match(rgx)) return unknown+offset_text;
const months = ['','January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const time_unformatted = unknown.split(', ');
var d;
var y;
var month;
var hm = time_unformatted[0];
if (time_unformatted.length==3) { //then we have HH:MM, DD Month, YYYY
let dM = time_unformatted[1].split(' ');
d = dM[0];
month = dM[1];
y = time_unformatted[2];
}
else if (time_unformatted.length==2){ //else we have HH:MM, DD Month YYYY or HH:MM, YYYY Month DD
let xMx = time_unformatted[1].split(' ');
month = xMx[1];
if (xMx[0].length<3){
d = xMx[0];
y = xMx[2];
}
else {
y = xMx[0];
d = xMx[2];
}
}
else {
console.log(unknown);
return false; //unexpected format
}
let m = months.indexOf(month);
let mm = (m<10 ? '0' : '')+m.toString();
let dd = (d.length<2 ? '0' : '')+d;
let date = y+'-'+mm+'-'+dd+'T'+hm+':00'+offset_text;
if (date.match(rgx)) return date;
return false;
}
function addWatchlistTimeDiffs(){
$('.mf-reltime').remove();
$('table.mw-changeslist-line').each(function(){
let ts = $(this).attr('data-mw-ts');
if (!ts) return;
let datetime = ts.slice(0,4)+'-'+ts.slice(4,6)+'-'+ts.slice(6,8)+'T'+ts.slice(8,10)+':'+ts.slice(10,12)+':'+ts.slice(12,14);
let unixtime = Date.parse(datetime);
let diff = new Date(datetime).humanDiff();
let recent = ( Date.now()-unixtime < 3600000 ? ' mf-recent' : '');
$(this).children('tbody').children('tr').children('td.mw-enhanced-rc').append(`<span ts="${unixtime}" class="mf-reltime${recent}">(${diff})</span>`);
});
}
function addOtherPagesTimeDiffs(){
$('a.ext-discussiontools-init-timestamplink, a.mw-changeslist-date, li.mw-logline-block>a').each(function(){
let date = formatDateFromVariousWikiDateFormats($(this).html());
if (!date) return;
try {
let unixtime = Date.parse(date);
let diff = new Date(date).humanDiff().replace(/\s/g, ' ');
let recent = ( Date.now()-unixtime < 3600000 ? ' mf-recent' : '');
$(this).append(`<span ts="${unixtime}" class="mf-reltime${recent}">(${diff})</span>`);
}
catch(error){
console.error(error);
}
});
}
function bindShowNewChanges(){
$(document).on( "ajaxComplete", function(event, request, settings) {
if (settings.url=='/w/api.php?format=json&action=query'){
addWatchlistTimeDiffs();
clearInterval(timestampUpdateTimer);
timestampUpdateTimer = setInterval(updateRecentHumanDiffs, 60000);
}
});
}
if (mw.config.values.wgPageName == "Special:Watchlist"){
addWatchlistTimeDiffs();
setTimeout(bindShowNewChanges, 10000);
}
else {
addOtherPagesTimeDiffs();
}
if (!$('.mf-reltime.mf-recent').length) return;
timestampUpdateTimer = setInterval(updateRecentHumanDiffs, 60000);
});