NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name StackExchange sites - convert dates to local timezone // @namespace darkred // @version 2019.8.28 // @description Converts dates to your local timezone // @author darkred // @license MIT // @include /^(https?:)?\/\/(www\.)?((3dprinting|academia|ai|alcohol|android|anime|apple|arduino|astronomy|aviation|bicycles|bioinformatics|biology|bitcoin|blender|boardgames|bricks|buddhism|chemistry|chess|chinese|christianity|civicrm|codegolf|codereview|coffee|communitybuilding|computergraphics|conlang|cooking|craftcms|crafts|crypto|cs|cseducators|cstheory|datascience|dba|devops|diy|drupal|dsp|earthscience|ebooks|economics|electronics|elementaryos|ell|emacs|engineering|english|eosio|esperanto|ethereum|expatriates|expressionengine|fitness|freelancing|french|gamedev|gaming|gardening|genealogy|german|gis|graphicdesign|ham|hardwarerecs|hermeneutics|hinduism|history|homebrew|hsm|interpersonal|iot|iota|islam|italian|japanese|joomla|judaism|korean|languagelearning|latin|law|lifehacks|linguistics|literature|magento|martialarts|math|matheducators|mathematica|mechanics|medicalsciences|meta|monero|money|movies|music|musicfans|mythology|networkengineering|opendata|opensource|or|outdoors|parenting|patents|pets|philosophy|photo|physics|pm|poker|politics|portuguese|psychology|puzzling|quant|quantumcomputing|raspberrypi|retrocomputing|reverseengineering|robotics|rpg|rus|russian|salesforce|scicomp|scifi|security|sharepoint|sitecore|skeptics|softwareengineering|softwarerecs|sound|space|spanish|sports|sqa|stats|stellar|sustainability|tex|tezos|tor|travel|tridion|ukrainian|unix|ux|vegetarianism|vi|video|webapps|webmasters|windowsphone|woodworking|wordpress|workplace|worldbuilding|writing)\.stackexchange\.com|(es|ja|pt|ru)\.stackoverflow\.com|(askubuntu|serverfault|stackapps|stackoverflow|superuser)\.com|mathoverflow\.net).*$/ // @grant none // @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.26/moment-timezone-with-data.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.6/jstz.min.js // @supportURL https://github.com/darkred/Userscripts/issues // ==/UserScript== /* eslint-disable quotes, no-console */ /* global jstz, moment */ var localTimezone = jstz.determine().name(); var serverTimezone = 'Europe/Berlin'; // GMT+1 function convertDates(dates) { // var dates = document.querySelectorAll('.relativetime, .rep-time'); var temp, temp2; for (var i = 0; i < dates.length; i++) { // 2019-08-24 03:26:50Z temp = moment(dates[i].title, 'YYYY-MM-DD HH:mm:ssZ', true); if (temp.isValid()) { dates[i].title = moment.tz(dates[i].title, serverTimezone).tz(localTimezone); } // Example URLS: // older, but of the same year: https://stackoverflow.com/questions?tab=newest&page=1200 // older, of previous years: https://stackoverflow.com/questions?tab=newest&page=120000 // Example timestamps: // Aug 7 at 6:45 // Aug 24 at 12:23 // Oct 24 '18 at 9:56 // Oct 24 '18 at 13:57 temp2 = dates[i].innerHTML.replace('at ', '').replace('\'', '') + ' Z'; var formatNoYear = 'MMM D H:mm Z'; var formatWithYear = 'MMM D YY H:mm Z'; var newMoment1 = moment(temp2, formatNoYear, true); var newMoment2 = moment(temp2, formatWithYear, true); if (newMoment1.isValid()){ dates[i].innerHTML = moment.tz(newMoment1, serverTimezone).tz(localTimezone).format('MMM D [at] H:mm'); } else if (newMoment2.isValid()){ dates[i].innerHTML = moment.tz(newMoment2, serverTimezone).tz(localTimezone).format("MMM D [']YY [at] H:mm"); } } } var dates = document.querySelectorAll('.relativetime, .rep-time'); convertDates(dates); // The part below is pointless to enable because the site's built-in feature that "the relative timestamps being increased every 1 min" becomes broken when this script is running /* // recalculate the relative times every 10 sec (function(){ convertDates(dates); setTimeout(arguments.callee, 1 * 60 * 1000); })(); */ var target = document.querySelectorAll('#question-mini-list, #questions, .rep-breakdown')[0], observer = new MutationObserver(function (mutations) { convertDates(); }), config = { characterData: true, subtree: true }; observer.observe(target, config);