I saw a forum post asking about creating custom 'World Clocks', so I figured I would write a quick guide for those of you who would like to do the same.
First of all, what is the 'World clock?' It is a Homepage UI item that we included with the default configuration as a sample of some of the cool things users could do in Service-now. You access it by selecting 'Add content >>' on a Homepage view. Select the 'World Clocks' > 'World Clocks' from the select menu and add it to a section of your Homepage:

The default 'World Clock' looks like this (in Firefox):

Not very pretty, right? Well that is because we just wanted to give you a taste of what you can do!
The code that creates those clocks is an open source Java script that is found in a UI Script called 'CoolClock', here is that code:
window.CoolClock = function(canvasId,displayRadius,skinId,showSecondHand,gmtOffset) { return this.init(canvasId,displayRadius,skinId,showSecondHand,gmtOffset); } CoolClock.findAndCreateClocks = function() { var canvases = document.getElementsByTagName("canvas"); for (var i=0;i<canvases.length;i++) { var fields = canvases[i].className.split(" ")[0].split(":"); if (fields[0] == "CoolClock") { new CoolClock(canvases[i].id,fields[2],fields[1],fields[3]!="noSeconds",fields[4]); } } } CoolClock.config = { clockTracker: {}, tickDelay: 1000, longTickDelay: 15000, defaultRadius: 85, renderRadius: 100, defaultSkin: "swissRail", skins: { // try making your own... swissRail: { outerBorder: { lineWidth: 1, radius:95, color: "black", alpha: 1 }, smallIndicator: { lineWidth: 2, startAt: 89, endAt: 93, color: "black", alpha: 1 }, largeIndicator: { lineWidth: 4, startAt: 80, endAt: 93, color: "black", alpha: 1 }, hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "black", alpha: 1 }, minuteHand: { lineWidth: 7, startAt: -15, endAt: 75, color: "black", alpha: 1 }, secondHand: { lineWidth: 1, startAt: -20, endAt: 85, color: "red", alpha: 1 }, secondDecoration: { lineWidth: 1, startAt: 70, radius: 4, fillColor: "red", color: "red", alpha: 1 } }, swissRailPM: { outerBorder: { lineWidth: 1, radius:95, color: "white", fillColor: "black", alpha: 1 }, smallIndicator: { lineWidth: 2, startAt: 89, endAt: 93, color: "white", alpha: 1 }, largeIndicator: { lineWidth: 4, startAt: 80, endAt: 93, color: "white", alpha: 1 }, hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "white", alpha: 1 }, minuteHand: { lineWidth: 7, startAt: -15, endAt: 75, color: "white", alpha: 1 }, secondHand: { lineWidth: 1, startAt: -20, endAt: 85, color: "red", alpha: 1 }, secondDecoration: { lineWidth: 1, startAt: 70, radius: 4, fillColor: "red", color: "red", alpha: 1 } }, chunkySwiss: { outerBorder: { lineWidth: 4, radius:97, color: "black", alpha: 1 }, smallIndicator: { lineWidth: 4, startAt: 89, endAt: 93, color: "black", alpha: 1 }, largeIndicator: { lineWidth: 8, startAt: 80, endAt: 93, color: "black", alpha: 1 }, hourHand: { lineWidth: 12, startAt: -15, endAt: 60, color: "black", alpha: 1 }, minuteHand: { lineWidth: 10, startAt: -15, endAt: 85, color: "black", alpha: 1 }, secondHand: { lineWidth: 4, startAt: -20, endAt: 85, color: "red", alpha: 1 }, secondDecoration: { lineWidth: 2, startAt: 70, radius: 8, fillColor: "red", color: "red", alpha: 1 } }, fancy: { outerBorder: { lineWidth: 5, radius:95, color: "green", alpha: 0.7 }, smallIndicator: { lineWidth: 1, startAt: 80, endAt: 93, color: "black", alpha: 0.4 }, largeIndicator: { lineWidth: 1, startAt: 30, endAt: 93, color: "black", alpha: 0.5 }, hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "blue", alpha: 0.7 }, minuteHand: { lineWidth: 7, startAt: -15, endAt: 92, color: "red", alpha: 0.7 }, secondHand: { lineWidth: 10, startAt: 80, endAt: 85, color: "blue", alpha: 0.3 }, secondDecoration: { lineWidth: 1, startAt: 30, radius: 50, fillColor: "blue", color: "red", alpha: 0.15 } }, machine: { outerBorder: { lineWidth: 60, radius:55, color: "#dd6655", alpha: 1 }, smallIndicator: { lineWidth: 4, startAt: 80, endAt: 95, color: "white", alpha: 1 }, largeIndicator: { lineWidth: 14, startAt: 77, endAt: 92, color: "#dd6655", alpha: 1 }, hourHand: { lineWidth: 18, startAt: -15, endAt: 40, color: "white", alpha: 1 }, minuteHand: { lineWidth: 14, startAt: 24, endAt: 100, color: "#771100", alpha: 0.5 }, secondHand: { lineWidth: 3, startAt: 22, endAt: 83, color: "green", alpha: 0 }, secondDecoration: { lineWidth: 1, startAt: 52, radius: 26, fillColor: "#ffcccc", color: "red", alpha: 0.5 } }, // these three created by bonstio from http://bonstio(.)net classic/*was gIG*/: { outerBorder: { lineWidth: 185, radius:1, color: "#E5ECF9", alpha: 1 }, smallIndicator: { lineWidth: 2, startAt: 89, endAt: 94, color: "#3366CC", alpha: 1 }, largeIndicator: { lineWidth: 4, startAt: 83, endAt: 94, color: "#3366CC", alpha: 1 }, hourHand: { lineWidth: 5, startAt: 0, endAt: 60, color: "black", alpha: 1 }, minuteHand: { lineWidth: 4, startAt: 0, endAt: 80, color: "black", alpha: 1 }, secondHand: { lineWidth: 1, startAt: -20, endAt: 85, color: "red", alpha: .85 }, secondDecoration: { lineWidth: 3, startAt: 0, radius: 2, fillColor: "black", color: "black", alpha: 1 } }, modern/*was gIG2*/: { outerBorder: { lineWidth: 185, radius:1, color: "#E5ECF9", alpha: 1 }, smallIndicator: { lineWidth: 5, startAt: 88, endAt: 94, color: "#3366CC", alpha: 1 }, largeIndicator: { lineWidth: 5, startAt: 88, endAt: 94, color: "#3366CC", alpha: 1 }, hourHand: { lineWidth: 8, startAt: 0, endAt: 60, color: "black", alpha: 1 }, minuteHand: { lineWidth: 8, startAt: 0, endAt: 80, color: "black", alpha: 1 }, secondHand: { lineWidth: 5, startAt: 80, endAt: 85, color: "red", alpha: .85 }, secondDecoration: { lineWidth: 3, startAt: 0, radius: 4, fillColor: "black", color: "black", alpha: 1 } }, simple/*was gIG3*/: { outerBorder: { lineWidth: 185, radius:1, color: "#E5ECF9", alpha: 1 }, smallIndicator: { lineWidth: 10, startAt: 90, endAt: 94, color: "#3366CC", alpha: 1 }, largeIndicator: { lineWidth: 10, startAt: 90, endAt: 94, color: "#3366CC", alpha: 1 }, hourHand: { lineWidth: 8, startAt: 0, endAt: 60, color: "black", alpha: 1 }, minuteHand: { lineWidth: 8, startAt: 0, endAt: 80, color: "black", alpha: 1 }, secondHand: { lineWidth: 5, startAt: 80, endAt: 85, color: "red", alpha: .85 }, secondDecoration: { lineWidth: 3, startAt: 0, radius: 4, fillColor: "black", color: "black", alpha: 1 } } } }; CoolClock.prototype = { init: function(canvasId,displayRadius,skinId,showSecondHand,gmtOffset) { this.canvasId = canvasId; this.displayRadius = displayRadius || CoolClock.config.defaultRadius; this.skinId = skinId || CoolClock.config.defaultSkin; this.showSecondHand = typeof showSecondHand == "boolean" ? showSecondHand : true; this.tickDelay = CoolClock.config[ this.showSecondHand ? "tickDelay" : "longTickDelay"]; this.canvas = document.getElementById(canvasId); this.canvas.setAttribute("width",this.displayRadius*2); this.canvas.setAttribute("height",this.displayRadius*2); this.canvas.style.width = this.displayRadius*2 + "px"; this.canvas.style.height = this.displayRadius*2 + "px"; this.renderRadius = CoolClock.config.renderRadius; this.scale = this.displayRadius / this.renderRadius; this.ctx = this.canvas.getContext("2d"); this.ctx.scale(this.scale,this.scale); this.gmtOffset = gmtOffset != null ? parseFloat(gmtOffset) : gmtOffset; CoolClock.config.clockTracker[canvasId] = this; this.tick(); return this; }, fullCircle: function(skin) { this.fullCircleAt(this.renderRadius,this.renderRadius,skin); }, fullCircleAt: function(x,y,skin) { with (this.ctx) { save(); globalAlpha = skin.alpha; lineWidth = skin.lineWidth; if (document.all) // excanvas doesn't scale line width so we will do it here lineWidth = lineWidth * this.scale; arc(x, y, skin.radius, 0, 2*Math.PI, false); if (document.all) // excanvas doesn't close the circle so let's color in the gap arc(x, y, skin.radius, -0.1, 0.1, false); if (skin.fillColor) { fillStyle = skin.fillColor fill(); } else { // XXX why not stroke and fill strokeStyle = skin.color; stroke(); } restore(); } }, radialLineAtAngle: function(angleFraction,skin) { with (this.ctx) { save(); translate(this.renderRadius,this.renderRadius); rotate(Math.PI * (2 * angleFraction - 0.5)); globalAlpha = skin.alpha; strokeStyle = skin.color; lineWidth = skin.lineWidth; if (document.all) // excanvas doesn't scale line width so we will do it here lineWidth = lineWidth * this.scale; if (skin.radius) { this.fullCircleAt(skin.startAt,0,skin) } else { beginPath(); moveTo(skin.startAt,0) lineTo(skin.endAt,0); stroke(); } restore(); } }, render: function(hour,min,sec) { var skin = CoolClock.config.skins[this.skinId]; this.ctx.clearRect(0,0,this.renderRadius*2,this.renderRadius*2); this.fullCircle(skin.outerBorder); for (var i=0;i<60;i++) this.radialLineAtAngle(i/60,skin[ i%5 ? "smallIndicator" : "largeIndicator"]); this.radialLineAtAngle((hour+min/60)/12,skin.hourHand); this.radialLineAtAngle((min+sec/60)/60,skin.minuteHand); if (this.showSecondHand) { this.radialLineAtAngle(sec/60,skin.secondHand); if (!document.all) // decoration doesn't render right in IE so lets turn it off this.radialLineAtAngle(sec/60,skin.secondDecoration); } }, nextTick: function() { setTimeout("CoolClock.config.clockTracker['"+this.canvasId+"'].tick()",this.tickDelay); }, stillHere: function() { return document.getElementById(this.canvasId) != null; }, refreshDisplay: function() { var now = new Date(); if (this.gmtOffset != null) { // use GMT + gmtOffset var offsetNow = new Date(now.valueOf() + (this.gmtOffset * 1000 * 60 * 60)); this.render(offsetNow.getUTCHours(),offsetNow.getUTCMinutes(),offsetNow.getUTCSeconds()); } else { // use local time this.render(now.getHours(),now.getMinutes(),now.getSeconds()); } }, tick: function() { if (this.stillHere()) { this.refreshDisplay() this.nextTick(); } } } _addLoadEvent(CoolClock.findAndCreateClocks);
The code that displays those clocks in the Homepage gauge is found in a UI Page called 'example_cool_clock', here is the default code:
<j:if test="${RP.isPreview()}"> <center>No preview available</center> </j:if> <j:if test="${!RP.isPreview()}"> <script language="javascript" src="scripts/excanvas.jsx?v=${gs.getProperty('glide.builddate')}"/> <script language="javascript" src="CoolClock.jsdbx?v=${gs.getProperty('glide.builddate')}"/> <!-- works on IE, but draws different --> <table><tr> <td align="center"><div><canvas id="x1" class="CoolClock:swissRail:30::-8 leftRightPad"></canvas></div>San Diego</td> <td align="center"><div><canvas id="x2" class="CoolClock::30:noSeconds:-45leftRightPad"></canvas></div>New York</td> <td align="center"><div><canvas id="x3" class="CoolClock::30:noSeconds:+0 leftRightPad"></canvas></div>London</td> <td align="center"><div><canvas id="x4" class="CoolClock:swissRailPM:30:noSeconds:+2 leftRightPad"></canvas></div>Kiev</td> </tr></table> </j:if>
What makes that UI Page appear in the 'Add content >>' box on a Homepage is a script found in a Widget, called 'World Clocks', here is that code:
function sections() { return { 'World Clocks' : { 'name' : 'example_cool_clock' } }; } function render() { var name = renderer.getPreferences().get("name") var gf = new GlideForm(renderer.getGC(), name, 0); gf.setDirect(true); gf.setRenderProperties(renderer.getRenderProperties()); return gf.getRenderedPage(); } function getEditLink() { return "sys_ui_page.do?sysparm_query=name=" + renderer.getPreferences().get("name"); }
This guide will show you the step by step directions on how to make your 'World Clocks' look like this:

If you want to tweak the code to customize even further, you can do that in the UI Script, but you will be on your own. If you do update the UI Script, and your clocks are not displaying properly, you may need to follow this guide, step by step, in order to get your clocks to appear correctly.
One final note, I do not believe this code automatically accounts for Daylight Savings Time, the calculations are off GMT, so you may have to manually update, although I am sure there is something out there that can automate that process too... If anybody knows of what that is, please send me the info and I will update the guide.
Thanks, and enjoy!