Last active
November 12, 2021 20:11
-
-
Save myersjustinc/6de3a20ef5a41088764edbb1ac37f4ec to your computer and use it in GitHub Desktop.
Bookmarklet to add time zone labels to Outlook 365's web-based calendar view
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
javascript:(function(){"use strict";const e='\n [role="main"] [aria-hidden="true"] > \n div > [aria-hidden="true"] time',t=`${e} abbr`;if(document.querySelectorAll(t).length)return;const r=new Date,n=document.querySelector('[role="main"]').getAttribute("aria-label"),o=parseInt(/\d{2}(?=:\d{2})/.exec(n)[0],10),a=[{formalName:%22America/Chicago%22,shortName:%22Central%22,abbr:%22CT%22},{formalName:%22America/New_York%22,shortName:%22Eastern%22,abbr:%22ET%22},{formalName:%22America/Los_Angeles%22,shortName:%22Pacific%22,abbr:%22PT%22}];a.forEach(function(e){const%20t=new%20Intl.DateTimeFormat(%22en-US%22,{timeZone:e.formalName,hour:%22numeric%22,minute:%22numeric%22,hour12:!1}).format(r),n=parseInt(/\d{2}(?=:\d{2})/.exec(t)[0],10);e.localHour=n,e.offsetFromOutlook=n-o}),document.querySelectorAll(e).forEach(function(e){if(null!=e.querySelector(%22abbr%22))return;const%20t=parseInt(e.textContent.trim(),10),r=document.createDocumentFragment();a.forEach(function(e,n){r.appendChild(function(e,t,r){const%20n=function(e,t){const%20r=t+e.offsetFromOutlook;return%20r%3C0?r+24:r%3E23?r-24:r}(e,t),o=document.createElement(%22abbr%22);return%20o.title=`\n%20%20%20%20%20%20${n.toString(10).padStart(2,%220%22)}:00\n%20%20%20%20%20%20${e.shortName}`.trim().replace(/\s+/g,%22%20%22),o.textContent=`\n%20%20%20%20%20%20${n}\n%20%20%20%20%20%20${e.abbr}`.trim().replace(/\s+/g,%22%20%22),o.style.display=%22block%22,o.style.textDecoration=%22none%22,r||(o.style.fontSize=%220.75em%22),o}(e,t,0===n))}),e.innerHTML=%22%22,e.appendChild(r)})})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
'use strict' | |
// Licensed ISC: | |
// | |
// Copyright 2021 Justin Myers | |
// | |
// Permission to use, copy, modify, and/or distribute this | |
// software for any purpose with or without fee is hereby | |
// granted, provided that the above copyright notice and this | |
// permission notice appear in all copies. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS | |
// ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL | |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO | |
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | |
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER | |
// RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
// OF THIS SOFTWARE. | |
// Find all the labels we want to augment | |
const timeSelector = ` | |
[role="main"] [aria-hidden="true"] > | |
div > [aria-hidden="true"] time` | |
const timeAbbrSelector = `${timeSelector} abbr` | |
if (document.querySelectorAll(timeAbbrSelector).length) { | |
return | |
} | |
// Figure out what time Outlook thinks it is | |
const now = new Date() | |
const outlookLabel = document.querySelector( | |
'[role="main"]').getAttribute('aria-label') | |
const outlookHour = parseInt( | |
/\d{2}(?=:\d{2})/.exec(outlookLabel)[0], 10) | |
// Figure out what time it is in each of our desired time zones, | |
// along with how far it is from Outlook's own time | |
const timeZones = [ | |
{ | |
formalName: 'America/Chicago', | |
shortName: 'Central', | |
abbr: 'CT' | |
}, | |
{ | |
formalName: 'America/New_York', | |
shortName: 'Eastern', | |
abbr: 'ET' | |
}, | |
{ | |
formalName: 'America/Los_Angeles', | |
shortName: 'Pacific', | |
abbr: 'PT' | |
} | |
] | |
timeZones.forEach(function(zone) { | |
const zoneFormat = new Intl.DateTimeFormat('en-US', { | |
timeZone: zone.formalName, | |
hour: 'numeric', | |
minute: 'numeric', | |
hour12: false | |
}) | |
const localTime = zoneFormat.format(now) | |
const localHour = parseInt( | |
/\d{2}(?=:\d{2})/.exec(localTime)[0], 10) | |
zone.localHour = localHour | |
zone.offsetFromOutlook = localHour - outlookHour | |
}) | |
// Build hour labels | |
function getZoneHour(zone, hourToLabel) { | |
const rawZoneHour = hourToLabel + zone.offsetFromOutlook | |
if (rawZoneHour < 0) { | |
return rawZoneHour + 24 | |
} | |
if (rawZoneHour > 23) { | |
return rawZoneHour - 24 | |
} | |
return rawZoneHour | |
} | |
function buildLabel(zone, hourToLabel, emphasize) { | |
const currentHour = getZoneHour(zone, hourToLabel) | |
const labelElem = document.createElement('abbr') | |
labelElem.title = ` | |
${currentHour.toString(10).padStart(2, '0')}:00 | |
${zone.shortName}`.trim().replace(/\s+/g, ' ') | |
labelElem.textContent = ` | |
${currentHour} | |
${zone.abbr}`.trim().replace(/\s+/g, ' ') | |
labelElem.style.display = 'block' | |
labelElem.style.textDecoration = 'none' | |
if (!emphasize) { | |
labelElem.style.fontSize = '0.75em' | |
} | |
return labelElem | |
} | |
// Update every hour label | |
const timeElements = document.querySelectorAll(timeSelector) | |
timeElements.forEach(function(timeElem) { | |
if (timeElem.querySelector('abbr') != null) { | |
return | |
} | |
const localHour = parseInt(timeElem.textContent.trim(), 10) | |
const labelsFragment = document.createDocumentFragment() | |
timeZones.forEach(function(zone, zoneIndex) { | |
labelsFragment.appendChild(buildLabel( | |
zone, localHour, zoneIndex === 0)) | |
}) | |
timeElem.innerHTML = '' | |
timeElem.appendChild(labelsFragment) | |
}) | |
}()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment