|
// Custom JavaScript for websites: https://chrome.google.com/webstore/detail/custom-javascript-for-web/poakhlngfciodnhlhhgnaaelnpjljija?hl=en |
|
// JSONView: https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc?hl=en |
|
// JSON Lite: https://chrome.google.com/webstore/detail/json-lite/acacmjcicejlmjcheoklfdchempahoag?hl=en |
|
(function () { |
|
var selector = '.type-number, span'; // JSONView, JSON Lite |
|
var attrName = 'cjs-timestamps-dates'; |
|
var storageName = 'cjs-timestamps-dates'; |
|
var observer; |
|
var timer; |
|
var pad = function (str, length) { |
|
str = String(str); |
|
while (str.length < (length || 2)) { |
|
str = '0' + str; |
|
} |
|
return str; |
|
}; |
|
// macOS clock format for easier comparison at a glance. |
|
var formatDateTimeMacOs = function (date) { |
|
var datestring = String(date); |
|
var dateparts = datestring.split(/\s+/); |
|
return ( |
|
dateparts[0] + ' ' + |
|
dateparts[1] + ' ' + |
|
date.getDate() + ' ' + |
|
(date.getFullYear() !== (new Date()).getFullYear() ? ', ' + date.getFullYear() + ' ' : '') + |
|
(date.getHours() >= 12 ? date.getHours() - 12 : date.getHours()) + ':' + |
|
pad(date.getMinutes()) + ':' + |
|
pad(date.getSeconds()) + ' ' + |
|
(date.getHours() >= 12 ? 'PM' : 'AM') + |
|
'' |
|
); |
|
}; |
|
// ISO-like format that is easier to parse with eyes. |
|
var formatDateTimeIsoLike = function (date) { |
|
var datestring = String(date); |
|
var dateparts = datestring.split(/\s+/); |
|
return ( |
|
pad(date.getFullYear(), 4) + '-' + |
|
pad(date.getMonth() + 1, 2) + '-' + |
|
pad(date.getDate(), 2) + ' ' + |
|
pad(date.getHours()) + ':' + |
|
pad(date.getMinutes()) + ':' + |
|
pad(date.getSeconds()) + '.' + |
|
pad(date.getMilliseconds(), 3) + ' ' + |
|
dateparts[5].replace(/^GMT/, '') + |
|
'' |
|
); |
|
}; |
|
// ISO-like format that is easier to parse with eyes, in UTC. |
|
var formatDateTimeIsoLikeUtc = function (date) { |
|
return ( |
|
pad(date.getUTCFullYear(), 4) + '-' + |
|
pad(date.getUTCMonth() + 1, 2) + '-' + |
|
pad(date.getUTCDate(), 2) + ' ' + |
|
pad(date.getUTCHours()) + ':' + |
|
pad(date.getUTCMinutes()) + ':' + |
|
pad(date.getUTCSeconds()) + '.' + |
|
pad(date.getUTCMilliseconds(), 3) + ' ' + |
|
'UTC' + |
|
'' |
|
); |
|
}; |
|
var getPreferredDateTimeFormat = function () { |
|
var format = 'macos'; // Default is questionable but convenient for now. |
|
try { |
|
format = localStorage.getItem(storageName + '__format') || format; |
|
} |
|
catch (ex) {} |
|
return format; |
|
}; |
|
var formatDateTime = function (date) { |
|
var format = getPreferredDateTimeFormat(); |
|
if (format === 'macos') { |
|
return formatDateTimeMacOs(date); |
|
} |
|
else if (format === 'isoutc') { |
|
return formatDateTimeIsoLikeUtc(date); |
|
} |
|
else { |
|
return formatDateTimeIsoLike(date); |
|
} |
|
}; |
|
var update = function () { |
|
var dataEls = window.document.querySelectorAll(selector); |
|
dataEls.forEach(function (dataEl) { |
|
var text = dataEl.firstChild.textContent.trim(); |
|
var datetimeEl = dataEl.querySelector('sup[' + attrName + ']'); |
|
var attr = (datetimeEl && datetimeEl.getAttribute(attrName)); |
|
if (attr && attr === text) { return; } |
|
var isMicroseconds = /^1[3456][0-9][0-9]{13}$/.test(text); |
|
var isMilliseconds = /^1[3456][0-9][0-9]{10}$/.test(text); |
|
if (!isMicroseconds && !isMilliseconds) { return; } |
|
var date; |
|
if (isMicroseconds) { |
|
date = (new Date(parseFloat(text) / 1000)); |
|
} |
|
else if (isMilliseconds) { |
|
date = (new Date(parseFloat(text))); |
|
} |
|
if (date) { |
|
datetimeEl = datetimeEl || document.createElement('sup'); |
|
datetimeEl.setAttribute(attrName, text); |
|
datetimeEl.innerText = ' ' + formatDateTime(date); |
|
datetimeEl.style.whiteSpace = 'pre'; |
|
datetimeEl.style.fontFamily = 'monospace'; |
|
datetimeEl.style.fontWeight = 'bold'; |
|
dataEl.appendChild(datetimeEl); |
|
} |
|
}); |
|
}; |
|
|
|
observer = new MutationObserver(function (mutations) { |
|
clearTimeout(timer); |
|
timer = setTimeout(update, 100); |
|
}); |
|
|
|
observer.observe(window.document.body, { |
|
attributes: true, |
|
childList: true, |
|
subtree: true |
|
}); |
|
|
|
window.addEventListener('load', update); |
|
})(); |