Edit in JSFiddle

/*
 * Begat : Original code by many, generic HTML5/Canvas clock example.
 * Date  : 12/30/2014
 * Who   : Sandy Ganz
 *
 * Revisions -
 *
 * 0.0  - 12/30/2014 sjg - Begat
 * 0.6  - 01/01/2015 sjg - Added face background inset to make more 3d like
 * 0.7  - 01/02/2015 sjg - Changed hoursOffset to work agaist date() so calendar updates OK,
 *                         added more comment, removed wastefull variable checks in drawPathFast().
 *                         Beginning of multiple clocks on page
 * 0.8  - 01/04/2015 sjg - Totally broke code in initial attempt to objectify it.
 * 0.9  - 02/23/2015 sjg - Fixed up timer with some hack code. Added static background draw, fixed
 *                         up hand angles and a few other bits. Still Hack, but at least working again.
 * 0.91 - 08/28/2015 sjg - Added wtfpl LICENSE AGREEMENT
 *                         
 *
 * Notes -
 *
 * This was a hack project that I was messing with. The original had poor optimization
 * and was drawing a lot more then needed. Worst was the vector drawing that used
 * a string with the coordinates. These were also changed to regular array for
 * performance. Exposed most setting via options. The default settings for options
 * are very noisy to show functionality, turn stuff off to clean up look!
 *
 * Todo -
 *
 * General code clean and comment. Some possible structural changes to have a 'class'
 * like structure called Clock that keeps things out of the global name space.
 * Rename some of the option variables to be more consistent or shorter (I haven't
 * decided yet).
 *
 * The big ones are make the functions that are specific generic, for example
 * annular ticks, bezels, etc. Right now they are hard coded with positions,
 * sizes, and so on. Oh yeah learn Javascript...
 *
 * Figure out how to create a snap shot of the canvas with all the shading and drawing
 * done once then animate the image back before drawing hands. I think this would
 * be faster at some point, but not sure. Good for an experiment or someone that
 * is a HTML5 badass ;)
 *
 * Oh yeah, a demo page maybe operations guide
 *
 * For many options you can use rgba() or #123456 style color settings.
 *
 * Features (many optional settings too) -
 *
 * Very nice looking HTML 5 / Javascript Clock
 * No incompatible CSS to deal with
 * User selectable Colors,  fonts and sizes for number and most text objects
 * Supports Time offsets from your local time
 * Display UTC as an options
 * Displays user positionable Date in several simple formats
 * Displays user positionable AM/PM indicator window
 * Displays PM 'dot' at above 12
 * Two user selectable text fields, font and position
 * Shaded and non shaded bezel options
 * Two sets of annular tick rings, inner and outer with many options
 * Pie slice lines from center of clock
 * Five Minute Numeric display Option (rotated)
 * Five Minute (offset by 2.5min) display dot
 * Triangle markers at 3, 6, 9, 12
 * 12 O'clock Dot
 * Display of all Large Hour numbers or only 3, 6, 9, 12
 * Sweep second hand or 'Quartz' ticker
 *
 * -------------------------------------------------------------------- 
 * Copyright (C) 2015 Sandy Ganz <[email protected]>
 * 
 * This work is free. You can redistribute it and/or modify it under the
 * terms of the Do What The Fuck You Want To Public License, Version 2,
 * as published by Sam Hocevar. See the COPYING file for more details.
 * (see below, yes this is a real license)
 * 
 * -------------------------------------------------------------------- 
 *         DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
 *                   Version 2, December 2004 
 *
 * Copyright (C) 2004 Sam Hocevar <[email protected]>
 * 
 * Everyone is permitted to copy and distribute verbatim or modified 
 * copies of this license document, and changing it is allowed as long 
 * as the name is changed. 
 *
 *           DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
 *  TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 
 *
 * 0. You just DO WHAT THE FUCK YOU WANT TO.
 * 
 * For more information on the license see www.wtfpl.net/faq/
 * -------------------------------------------------------------------- 
 * 
 */


// all paths are CLOSED, and based from the center point of 0,0
// The FIRST element in each array is the contex moveTo for start of path
var pie_path = [
    [-108, -1],
    [108, -1],
    [108, -1],
    [-108, -1]
];
var tri_path = [
    [154, 0],
    [178, -6],
    [178, 6]
];
var inner_tick_head_path = [
    [110, -3],
    [120, -3],
    [120, 3],
    [110, 3]
];
var inner_tick_path = [
    [114, -0.5],
    [120, -0.5],
    [120, 0.5],
    [114, 0.5]
];
var outer_tick_pill_path = [
    [156, -2],
    [180, -2],
    [180, 2],
    [156, 2]
];
var outer_tick_head_path = [
    [180, -3],
    [184, -3],
    [184, 3],
    [180, 3]
];
var outer_tick_major_path = [
    [174, -0.5],
    [184, -0.5],
    [184, 0.5],
    [174, 0.5]
];
var outer_tick_minor_path = [
    [180, -0.3],
    [184, -0.3],
    [184, 0.3],
    [180, 0.3]
];

var sec_hand_path = [
    [-50, 0],
    [-45, -5],
    [-25, -5],
    [-22, -2],
    [22, -2],
    [25, -5],
    [180, 0],
    [25, 5],
    [22, 2],
    [-22, 2],
    [-25, 5],
    [-45, 5]
];

var min_hand_path = [
    [0, 0],
    [1, -2],
    [20, -2],
    [22, -5],
    [122, -5],
    [124, -2],
    [146, -2],
    [168, 0],
    [146, 2],
    [124, 2],
    [122, 5],
    [22, 5],
    [20, 2],
    [1, 2],
    [0, 0],
    [24, 0],
    [24, 2],
    [120, 2],
    [122, 0],
    [120, -2],
    [24, -2],
    [24, 0]
];

var hour_hand_path = [
    [0, 0],
    [1, -3],
    [14, -3],
    [17, -7],
    [97, -7],
    [100, -3],
    [112, -2],
    [134, 0],
    [112, 2],
    [100, 3],
    [97, 7],
    [17, 7],
    [14, 3],
    [1, 3],
    [0, 0],
    [18, 0],
    [21, 3],
    [94, 3],
    [96, 0],
    [94, -3],
    [21, -3],
    [18, 0]
];

function myclock(id) {
    var clk = new Clock(id);
    var clkOpts = clk.getClockOpts(); //cheezeee returns ref to object so now public
    var textOpts = clk.getTextOpts();
    
    clkOpts.smoothTicks = false;
    textOpts.text1 = 'Quartz';
    textOpts.text1Color = '#ff0000';
    textOpts.text1OffsetY= -80;

    textOpts.text2 = 'Chronometer';
    textOpts.text2Font = 'bold italic 20px Georgia';
    clk.redraw();    // force update of background on next tick event
    return clk;
}

function myclock1(id) {
    var clk = new Clock(id);
    return clk;
}

/*var schedule = {
    start,
    end,
    free,
    subject
}*/

function myclock2(id,schedule, opts) {
    
    var ns = []; // schedule with free times
    var s = schedule[0];
    startHr = s.start.substring(0,2);
    startMn = s.start.substring(3,5);
    if ((startHr > 7 ) ||
        ((startHr = 7 ) && (startMn > 0 ))) {
        ns.push({start:"07:00",end:s.start,free:true});
    }
    var prevEndHr, prevEndMn;
    schedule.forEach(s => {
        startHr = s.start.substring(0,2);
        startMn = s.start.substring(3,5);
        endHr = s.end.substring(0,2);
        endMn = s.end.substring(3,5);
        if ((prevEndHr) && ((prevEndHr != startHr) || (prevEndMn != startMn))) {
            ns.push({start:prevEndHr+":"+prevEndMn,end:startHr+":"+startMn,free:true});
        }
        ns.push({start:startHr+":"+startMn,end:endHr+":"+endMn,subject:s.subject});
        if (schedule.indexOf(s) == schedule.length - 1) {
            ns.push({start:endHr+":"+endMn,end:"07:00",free:true});
        }
        prevEndHr = endHr;
        prevEndMn = endMn;
    });

    if (opts["nofree"]) {
        var clk = new Clock(id,schedule); // if schedule is used then free times are not marked
    }
    else {
        var clk = new Clock(id,ns); // if schedule is used then free times are not marked
    }
    var bezOpts = clk.getBezelOpts();
    var clkOpts = clk.getClockOpts();
    var textOpts = clk.getTextOpts();
    var tickOpts = clk.getTickOpts();
    bezOpts.bezel5Draw = true;
    textOpts.text2 = "";
    textOpts.text1 = "";
    tickOpts.innerTick = false;
    tickOpts.innerTickHead = false;
    tickOpts.pie = false;

    clk.redraw();
}

function Clock(id,schedule) {

    var bezelOpts = {
    
        // Outer most ring, drawn first, other bezels layer on top
        // These are all size by the RADIUS 250 is the working size of the
        // clock. Bezel operations can be as complex as needed as they are
        // outsize of the animation drawing. Once drawn the do not need
        // refresh
    
        // Simple thickness bezel
        bezel1Draw: false,
        bezel1Color: '#111',
        bezel1Diameter: 250,
    
        // Simple thickness bezel
        bezel2Draw: false,
        bezel2Color: '#aaa',
        bezel2Diameter: 248,
    
        // shaded bezel
        bezel3Draw: true,
        bezel3StartColor: '#555555',
        bezel3StopColor: '#000000',
        bezel3Diameter: 245,
    
        // shaded bezel
        bezel4Draw: false,
        bezel4StartColor: '#ff5555',
        bezel4StopColor: '#ff0000',
        bezel4Diameter: 224,
    
        // shaded bezel
        bezel5Draw: false,
        bezel5FreeColor: '#00ff00',
        bezel5BusyColor: '#ff0000',
        bezel5Diameter: 230,
    };
    
    // general clock face options
    var faceOpts = {
        // General face background options, this draws over the bezels
        faceColor: '#ffffff', // background color of the face
        faceDiameter: 220, // diameter of the filled face
        faceInset: true, // simulate depth with shadow
    };
    
    // text display options, coords from center of clock, - is UP, + down
    var textOpts = {
        text1: 'Simplex',
        text1Color: '#ff5555',
        text1Font: '30px Georgia',
        text1OffsetX: 0,
        text1OffsetY: -75,
    
        text2: 'Analog Chronometer',
        text2Color: '#111111',
        text2Font: '20px Georgia',
        text2OffsetX: 0,
        text2OffsetY: 75,
    };
    
    // date display options
    
    var dateOpts = {
        dateTextColor: '#111111',
        dateFont: '22px Georgia',
        dateOffsetX: 0,
        dateOffsetY: 40,
        dateBox: true, // show in inset box
        dateBoxColor: '#ffffff',
        dateUTC: false, // use javascript UTC time
        dateShort: false, // display just date as number  
    };
    
    // Lots of stuff here mainly related to the annular tick rings and
    // other indicators around the rings really should be split up
    
    var tickOpts = {
    
        // triangles at 3, 6, 9 and 12
        tri: true,
        triColor: '#555555',
    
        // pie slices from the center of the clock
        pie: true,
        pieColor: '#dddddd',
        pieLineWidth: 2,
    
        // large hour numbers
        hourNums: true,
        hoursComplete: true, // show 1-12 if true, otherwise just 3, 6, 9 and 12
        hourColor: '#cc0000',
        hourFont: '30pt Georgia',
        hourOffset: 140, // offset from the center of the clock
    
        // inner tick ring
        innerTick: true,
        innerTickHead: true, // draws thick 5 minute markers 
        innerTickColor: '#aaaaaa',
        innerTickHeadColor: '#555555',
    
        // outer tick ring
    
        // draws tick head markers at 5 min marks
        outerTickHead: true,
        outerTickHeadColor: '#ff0000',
    
        // draws think line UNDER the 5 min tick head
        outerTickPill: true,
        outerTickPillColor: '#aaaaaa',
    
        // draws the finest tick marks
        outerTickMinor: true,
        outerTickMinorColor: '#aaaaaa',
    
        // draws the finest tick marks
        outerTickMajor: true,
        outerTickMajorColor: '#444000',
    
        // draws the dot over the 12 o'clock postion
        outer12Dot: true,
        outer12DotColor: '#ff0000',
    
        // draws the outer dots at 2.5min marks
        outerDots: true,
        outerDotsOffset: 195, // offset from the center of the clock  
        outerDotsSize: 3.0, // radius of the dot, fractional OK
        outerDotsColor: '#ff0000',
    
        // outer rotated minute numbers
        outerMinNums: true,
        outerMinNumsOffset: 195, // offset from the center of the clock
        outerMinNumsFont: '12pt Georgia',
        outerMinNumsColor: '#555555',
    };
    
    // general hand options
    var handOpts = {
        secPivot: true, // draws dot over center of hands
        secPivotColor: '#c21',
        secHandColor: '#c21',
        minHandColor: '#222222',
        hourHandColor: '#333333',
    };
    
    // options related to AM/PM indications
    var ampmOpts = {
        ampmDot: true, // show a tranparent dot over the 12 pm position
        amTextColor: '#000000', // AM/PM indicator text color if AM
        pmTextColor: '#000000', // AM/PM indicator text color if PM
        ampmFont: '22px Georgia',
        ampmBox: true, // Show indicator as inset
        amBoxColor: '#ffffff', // color of inset if AM
        pmBoxColor: '#bbbbbb', // color of insert if PM
        ampmOffsetX: 0, // X offset from center of clock 
        ampmOffsetY: -40, // Y offset from center of clock
    };
    
    // General clock options
    var clockOpts = {
        smoothTicks: true, // smooth sweep second hand
        hoursOffset: 0, // offset from current time (Local or UTC), may have some glitches
        useUTC: false, // use UTC as base for time
    };
        
    // instance vars
    var d,ds;
    var scale = 1;
    var interval_id = null;
    var ctx, back_ctx;
    var self = this;
    var interval = 31; //millisecs default for very smooth action, if not using smooth tics can be much higher
    var canvas = document.getElementById(id);
    var refresh = false;
    
    if (!canvas.getContext) {
        alert('Canvas not supported, can\'t draw clock');
        return;
    }
    
    ds = new Date(); // just to set it up
    d = new Date();     // aways pull new date
    
    if (clockOpts.hoursOffset != 0) // Add offset to new time, hopefull works OK with date
        d = new Date(d.getTime() + clockOpts.hoursOffset * 3600000);
    
    // set up pre computed options, and one time drawing that
    // don't get affected by hands or other display changes

    pie_path[3][1] = tickOpts.pieLineWidth - 1;
    pie_path[2][1] = tickOpts.pieLineWidth - 1;

    ctx = canvas.getContext('2d');

    canvas.width = 500 * scale; // base size is all drawn at 500x500
    canvas.height = 500 * scale;

    ctx.scale(scale, scale); // hint to get different sized clocks, adj canvas too
    
    var back_canvas = document.createElement("canvas");

    if (!back_canvas.getContext) {
        alert('Canvas not supported, can\'t draw clock');
        return;
    }

    back_canvas.id = id + '-hidden';
    back_canvas.style.hidden = true;    // not sure if works or needed
    
    var back_ctx = back_canvas.getContext('2d');    
    back_canvas.width = 500;
    back_canvas.height = 500;    

    // start and stop functions, must call start() to get clock ticking
    this.start = function() {
        interval_id = setInterval(function() {self.ticker()}, interval);
    }
    
    this.stop = function() {
        if(interval_id != null){
            clearInterval(interval_id);
            interval_id = null;
        }
    }
    
    this.redraw = function() {
        refresh = true;
    }

    this.getClockOpts = function() {
        return clockOpts;
    }

    this.getBezelOpts = function() {
        return bezelOpts;
    }

    this.getTextOpts = function() {
        return textOpts;
    }
    
    this.getTickOpts = function() {
        return tickOpts;
    }
    
    // called to update clock time from timeout/interval
    this.ticker = function () {
        var h;
        
        // adjust time offset if needed

        d = new Date();     // aways pull new date and time

        if (clockOpts.hoursOffset != 0) // Add offset to new time, hopefull works OK with date
            d = new Date(d.getTime() + clockOpts.hoursOffset * 3600000);

        // get system 
        if (clockOpts.useUTC) h = d.getUTCHours();
        else h = d.getHours();

        // set up the hands and relationships (they are all dependant)
        var m = d.getMinutes();
        var s = d.getSeconds();
        var ms = (clockOpts.smoothTicks) ? d.getMilliseconds() : 0;    // if using quarts like ticks 0 ms
        
        var secAngle = -90 + s * 6 + ms * 0.006;
        var minAngle = -90 + m * 6 + s * 0.1 + ms * 0.0001;
        var hourAngle = -90 + h * 30 + m * 0.5 + s / 120;

        ctx.clearRect(0, 0, 500, 500);        // always clear entire space
        ctx.drawImage(back_canvas, 0, 0);     // draw pre drawn background to top   

        // refresh background on hour change, will catch day change too for calendar
        if(ds.getHours() != d.getHours() || refresh)
        {
            ds = d;
            this.drawBackground();                  // refresh the background to catch changes
            ctx.drawImage(back_canvas, 0, 0);        // draw background again
            refresh = false;
        }

        if(ds.getMinutes() != d.getMinutes() || refresh)
        {
            ds = d;
            this.drawBackground();                  // refresh the background to catch changes
            ctx.drawImage(back_canvas, 0, 0);        // draw background again
            refresh = false;
        }

        // hand vectors need translation to center, these all draw to the front ctx/canvas
        ctx.translate(250, 250);
        this.drawHourHand(hourAngle, handOpts);
        this.drawMinHand(minAngle, handOpts);
        this.drawSecHand(secAngle, handOpts);
        ctx.translate(-250, -250);
    }

    
    // Draw all background items here. This doesn't get refreshed often, all draw to back ctx
    this.drawBackground = function()
    {
        this.drawBezels(bezelOpts);
        this.drawFace(faceOpts);
        this.drawTicks(tickOpts);
        this.drawText(textOpts);
        this.drawDate(dateOpts);
        this.drawAMPM(ampmOpts);
    }
    
    this.drawInsetBox = function (bk_color, shadow_color, offX, offY, width, height) {
        back_ctx.save();
        back_ctx.beginPath();
        back_ctx.fillStyle = bk_color;
        back_ctx.rect(offX, offY, width, height);
        back_ctx.closePath();
        back_ctx.fill();

        back_ctx.beginPath();
        back_ctx.rect(offX, offY, width, height);
        back_ctx.clip();

        back_ctx.beginPath();
        back_ctx.strokeStyle = shadow_color;
        back_ctx.lineWidth = 4;
        back_ctx.shadowBlur = 5;
        back_ctx.shadowColor = shadow_color;
        back_ctx.shadowOffsetX = 4;
        back_ctx.shadowOffsetY = 2;
        width += 4;
        back_ctx.strokeRect(offX - 2, offY - 2, width, height + 4);
        back_ctx.stroke();
        back_ctx.restore();
    };

    this.drawBezels = function (opts) {
        // Outer most Ring, bezel1Ring
        if (opts.bezel1Draw) {
            back_ctx.beginPath();
            back_ctx.arc(250, 250, opts.bezel1Diameter, 0, 6.2831); //2*pi
            back_ctx.fillStyle = opts.bezel1Color;
            back_ctx.fill();
            back_ctx.closePath();
        }

        // next thin ring
        if (opts.bezel2Draw) {
            back_ctx.beginPath();
            back_ctx.arc(250, 250, opts.bezel2Diameter, 0, 6.2831); //2*pi
            back_ctx.fillStyle = opts.bezel2Color;
            back_ctx.fill();
            back_ctx.closePath();
        }

        var gx1, gy1, gx2, gy2, g;

        if (opts.bezel3Draw) {
            gx1 = 127; // 250 + 246 * Math.cos(4 / 3 * Math.PI);
            gy1 = 35; // 250 + 246 * Math.sin(4 / 3 * Math.PI)
            gx2 = 373; // 250 + 246 * Math.cos(1 / 3 * Math.PI);
            gy2 = 463; // 250 + 246 * Math.sin(1 / 3 * Math.PI);
            g = back_ctx.createLinearGradient(gx1, gy1, gx2, gy2);
            g.addColorStop(0, opts.bezel3StartColor); // outer ring reflect
            g.addColorStop(1, opts.bezel3StopColor); // outer ring dark

            //  outer ring
            back_ctx.beginPath();
            back_ctx.arc(250, 250, opts.bezel3Diameter, 0, 6.2831); //2*pi
            back_ctx.fillStyle = g;
            back_ctx.fill();
            back_ctx.closePath();
        }

        if (opts.bezel4Draw) {
            gx1 = 138; // 250 + 224 * Math.cos(4 / 3 * Math.PI);
            gy1 = 56; // 250 + 224 * Math.sin(4 / 3 * Math.PI)
            gx2 = 362; // 250 + 224 * Math.cos(1 / 3 * Math.PI);
            gy2 = 326; // 250 + 224 * Math.sin(1 / 3 * Math.PI);
            g = back_ctx.createLinearGradient(gx1, gy1, gx2, gy2);

            // inner ring
            g.addColorStop(0, opts.bezel4StartColor); // outer ring reflect
            g.addColorStop(1, opts.bezel4StopColor); // outer ring dark
            back_ctx.beginPath();
            back_ctx.arc(250, 250, opts.bezel4Diameter, 0, 6.2831); //2*pi
            back_ctx.fillStyle = g;
            back_ctx.fill();
            back_ctx.closePath();
        }

        if (opts.bezel5Draw && schedule) {
            // schedule ring

            var arcstart, arcend;
            schedule.forEach(s => {
                
                startHr = s.start.substring(0,2);
                startMn = s.start.substring(3,5);
                endHr = s.end.substring(0,2);
                endMn = s.end.substring(3,5);

                currTime = d.getHours()*60+d.getMinutes();
                startTime = startHr*60+parseInt(startMn);
                endTime = endHr*60+parseInt(endMn)

                back_ctx.beginPath();

                if (startHr < 15 ) {
                    arcstart = 2 * Math.PI - ( 15 - startHr ) * Math.PI / 6 + startMn * Math.PI / 360;
                }
                else{
                    arcstart = ( startHr - 15 ) * Math.PI / 6 + startMn * Math.PI / 360;
                }
                if (endHr < 15) {
                    arcend = 2 * Math.PI - ( 15 - endHr ) * Math.PI / 6 + endMn * Math.PI / 360;
                }
                else{
                    arcend = ( endHr - 15 ) * Math.PI / 6 + endMn * Math.PI / 360;
                }
                back_ctx.arc(250, 250, bezelOpts.bezel5Diameter, arcstart, arcend); //2*pi
        
                back_ctx.strokeStyle = s.free?bezelOpts.bezel5FreeColor:bezelOpts.bezel5BusyColor;
                back_ctx.lineWidth = 10;
                back_ctx.stroke();
                back_ctx.closePath();

                if ((currTime >= startTime) && (typeof(s.free) == "undefined")) {

                    back_ctx.beginPath();
                    if (startHr < 15 ) {
                        arcstart = 2 * Math.PI - ( 15 - startHr ) * Math.PI / 6 + startMn * Math.PI / 360;
                    }
                    else{
                        arcstart = ( startHr - 15 ) * Math.PI / 6 + startMn * Math.PI / 360;
                    }
                    if (currTime <= endTime) {
                        if (d.getHours() < 15) {
                            arcend = 2 * Math.PI - ( 15 - d.getHours() ) * Math.PI / 6 + d.getMinutes() * Math.PI / 360;
                        }
                        else{
                            arcend = ( d.getHours() - 15 ) * Math.PI / 6 + d.getMinutes() * Math.PI / 360;
                        }
                    }
                    else {
                        if (endHr < 15) {
                            arcend = 2 * Math.PI - ( 15 - endHr ) * Math.PI / 6 + endMn * Math.PI / 360;
                        }
                        else{
                            arcend = ( endHr - 15 ) * Math.PI / 6 + endMn * Math.PI / 360;
                        }
                    }
                    back_ctx.arc(250, 250, bezelOpts.bezel5Diameter, arcstart, arcend); //2*pi
            
                    back_ctx.strokeStyle = "grey";
                    back_ctx.lineWidth = 10;
                    back_ctx.stroke();
                    back_ctx.closePath();
                }


            });
        }
    }

    this.drawFace = function (opts) {
        // background face, usally redrawn OVER bezels, and MUST
        back_ctx.beginPath();
        back_ctx.arc(250, 250, opts.faceDiameter, 0, 6.2831); //2*pi
        back_ctx.fillStyle = opts.faceColor;
        back_ctx.closePath();
        back_ctx.fill();

        // create a shaded area to simulate 3D shadow
        if (opts.faceInset) {
            back_ctx.save();

            back_ctx.beginPath();
            back_ctx.arc(250, 250, opts.faceDiameter, 0, 6.2831); //2*pi
            back_ctx.clip();

            back_ctx.beginPath();
            back_ctx.strokeStyle = 'black';
            back_ctx.lineWidth = 6;
            back_ctx.shadowBlur = 10;
            back_ctx.shadowColor = 'black';
            back_ctx.shadowOffsetX = 4;
            back_ctx.shadowOffsetY = 1;
            back_ctx.arc(250, 250, opts.faceDiameter + 3, 0, 6.2831); //2*pi
            back_ctx.stroke();
            back_ctx.restore();
        }
    }

    this.drawText = function (opts) {
        // clock text
        back_ctx.beginPath();
        back_ctx.textAlign = 'center';
        back_ctx.textBaseline = 'middle';

        back_ctx.font = opts.text1Font;
        back_ctx.fillStyle = opts.text1Color;
        back_ctx.fillText(opts.text1, 250 + opts.text1OffsetX, 250 + opts.text1OffsetY);

        back_ctx.font = opts.text2Font;
        back_ctx.fillStyle = opts.text2Color;
        back_ctx.fillText(opts.text2, 250 + opts.text2OffsetX, 250 + opts.text2OffsetY);

        back_ctx.fill();
        back_ctx.closePath();
    };

    this.drawDate = function (opts) {
        back_ctx.save();
        if (opts.dateUTC) {
            if (opts.dateShort) datestr = d.getUTCDate();
            else datestr = 'UTC : ' + d.getUTCDate() + '-' + d.getUTCMonth() + '-' + d.getUTCFullYear();
        } else if (opts.dateShort) datestr = d.getDate();
        else datestr = d.toDateString();

        back_ctx.font = opts.dateFont;
        width = back_ctx.measureText(datestr).width + 14;

        if (false && opts.dateBoxShadow && opts.dateBox) {
            back_ctx.shadowColor = '#aaaaaa';
            back_ctx.shadowBlur = 10;
            back_ctx.shadowOffsetX = 3;
            back_ctx.shadowOffsetY = 3;
        }

        if (opts.dateBox) {

            this.drawInsetBox(opts.dateBoxColor, 'black', 250 + opts.dateOffsetX - width / 2, 250 + opts.dateOffsetY - 15, width, 30);
        }
        back_ctx.restore();

        back_ctx.font = opts.dateFont;

        back_ctx.beginPath();
        back_ctx.textAlign = 'center';
        back_ctx.textBaseline = 'middle';
        back_ctx.fillStyle = opts.dateTextColor;
        back_ctx.fillText(datestr, 250 + opts.dateOffsetX, 250 + opts.dateOffsetY);
        back_ctx.fill();
        back_ctx.closePath();
    }

    this.drawAMPM = function (opts) {
        if (d.getHours() > 11) {
            ampmstr = 'PM';
            pm = true;
        } else {
            ampmstr = 'AM';
            pm = false;
        }

        back_ctx.font = opts.ampmFont;
        width = back_ctx.measureText(ampmstr).width + 10;

        back_ctx.save();

        if (opts.ampmBox) {
            background = (pm) ? opts.pmBoxColor : opts.amBoxColor;
            shadow = 'black';
            this.drawInsetBox(background, shadow, opts.ampmOffsetX + 250 - width / 2, 250 + opts.ampmOffsetY - 15, width, 30);
        }

        back_ctx.restore();

        if (opts.ampmDot && pm) {
            // 12 o'clock dot PM Dot

            back_ctx.beginPath();
            back_ctx.fillStyle = 'rgba(0,0,0,.50)';
            back_ctx.arc(250, 55, 10, 0, 6.2831); //2*pi
            back_ctx.closePath();
            back_ctx.fill();
        }

        back_ctx.font = opts.ampmFont;

        back_ctx.beginPath();
        back_ctx.textAlign = 'center';
        back_ctx.textBaseline = 'middle';
        back_ctx.fillStyle = (pm) ? opts.pmTextColor : opts.amTextColor;

        back_ctx.fillText(ampmstr, 250 + opts.ampmOffsetX, 250 + opts.ampmOffsetY);
        back_ctx.closePath();
        back_ctx.fill();
    }

    this.drawTicks = function (opts) {
        var lbl, x, y, i;

        back_ctx.translate(250, 250);

        // inner pie slices
        if (opts.pie) {
            this.drawPathBk(pie_path, opts.pieColor, 0);
            this.drawPathBk(pie_path, opts.pieColor, 30);
            this.drawPathBk(pie_path, opts.pieColor, 60);
            this.drawPathBk(pie_path, opts.pieColor, 90);
            this.drawPathBk(pie_path, opts.pieColor, 120);
            this.drawPathBk(pie_path, opts.pieColor, 150);
        }

        // triangle tics

        if (opts.tri) {
            this.drawPathBk(tri_path, opts.triColor, 0);
            this.drawPathBk(tri_path, opts.triColor, 90);
            this.drawPathBk(tri_path, opts.triColor, 180);
            this.drawPathBk(tri_path, opts.triColor, -90);
        } // outer ticks

        if (opts.outerTickPill) {
            this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, 30);
            this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, 60);
            this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, 120);
            this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, 150);
            this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, -30);
            this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, -60);
            this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, -120);
            this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, -150);

            if (!opts.tri) // no triangles, draw ticks in those slots too
            {
                this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, 0);
                this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, 90);
                this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, 180);
                this.drawPathBk(outer_tick_pill_path, opts.outerTickPillColor, 270);
            }
        }

        // Hour Numbers
        if (opts.hourNums) {
            for (i = -60; i < 300; i += 30) {
                // large hour numbers

                if (!opts.hoursComplete) if (!(i == 270 || i == 180 || i == 90 || i == 0)) continue;

                lbl = '' + Math.round(i / 30 + 3);
                x = opts.hourOffset * Math.cos(i * 0.017453); // Math.PI / 180.0);
                y = opts.hourOffset * Math.sin(i * 0.017453); // Math.PI / 180.0);

                back_ctx.save();
                back_ctx.translate(x, y);
                back_ctx.font = opts.hourFont;
                back_ctx.textAlign = 'center';
                back_ctx.textBaseline = 'middle';
                back_ctx.fillStyle = opts.hourColor;
                back_ctx.fillText(lbl, 0, 0);
                back_ctx.restore();
            }
        }

        if (opts.outer12Dot) {
            // 12 o'clock dot
            back_ctx.beginPath();
            back_ctx.arc(0, -195, 4, 0, 6.2831); //2*pi
            back_ctx.fillStyle = opts.outer12DotColor;
            back_ctx.fill();
            back_ctx.closePath();
        }

        for (i = 0; i < 360; i += 30) {
            // outer tick pills
            if (opts.outerTickHead) this.drawPathBk(outer_tick_head_path, opts.outerTickHeadColor, i);

            // inner tick pills
            if (opts.innerTickHead) this.drawPathBk(inner_tick_head_path, opts.innerTickHeadColor, i);

            // outer small numbers
            if (opts.outerMinNums) {
                lbl = '' + Math.round(i / 6 + 15);
                if (lbl == '60') // show zero if no dot 
                if (opts.outer12Dot) lbl = '';
                else lbl = '0';

                if (lbl == '65') lbl = '5'; //hack
                if (lbl == '70') lbl = '10'; //hack

                x = opts.outerMinNumsOffset * Math.cos(i * 0.017453);
                y = opts.outerMinNumsOffset * Math.sin(i * 0.017453);

                back_ctx.save();
                back_ctx.translate(x, y);
                back_ctx.rotate((i + 90 - (i > 0 && i < 180 ? 180 : 0)) * 0.017453);
                back_ctx.font = opts.outerMinNumsFont;
                back_ctx.textAlign = 'center';
                back_ctx.textBaseline = 'middle';
                back_ctx.fillStyle = opts.outerMinNumsColor;
                back_ctx.fillText(lbl, 0, 0);
                back_ctx.restore();
            }

            // small dots between small numbers
            if (opts.outerDots) {
                back_ctx.beginPath();
                x = opts.outerDotsOffset * Math.cos((i + 15) * 0.017453);
                y = opts.outerDotsOffset * Math.sin((i + 15) * 0.017453);
                back_ctx.arc(x, y, opts.outerDotsSize, 0, 6.2831); //2*pi
                back_ctx.fillStyle = opts.outerDotsColor;
                back_ctx.fill();
                back_ctx.closePath();
            }

            // outiner ring tics, major, minor, inner ring with smart backfill for missing ticks

            for (var j = 0; j < 25; j += 6) {
                if (j != 0 || !(opts.outerTickHead || opts.outerTickPill)) // fill in major ticks if head or pills not drawn
                {
                    // major outer ring
                    if (opts.outerTickMajor) this.drawPathBk(outer_tick_major_path, opts.outerTickMajorColor, i + j);
                }

                if (j != 0 || !opts.innerTickHead) // if not drawing tick heads and inner ticks enabled fill them in too
                {
                    // inner ring major 
                    if (opts.innerTick) this.drawPathBk(inner_tick_path, opts.innerTickColor, i + j);
                }

                if (opts.outerTickMinor) // fine ticks, back fill if majors are not drawn
                {
                    var k = (opts.outerTickMajor) ? 1.5 : 0;
                    for (; k < 5; k += 1.5)
                    this.drawPathBk(outer_tick_minor_path, opts.outerTickMinorColor, i + j + k);
                }
            }
        }

        back_ctx.translate(-250, -250);
    }

    this.drawSecHand = function (ang, opts) {
        this.drawPathFr(sec_hand_path, opts.secHandColor, ang);

        if (opts.secPivot) {
            ctx.beginPath();
            ctx.arc(0, 0, 8, 0, 6.2831); //2*pi
            ctx.fillStyle = opts.secPivotColor;
            ctx.fill();
            ctx.closePath();
        }
    }

    this.drawMinHand = function (ang, opts) {
        this.drawPathFr(min_hand_path, opts.minHandColor, ang);
    }

    this.drawHourHand = function (ang, opts) {
        this.drawPathFr(hour_hand_path, opts.hourHandColor, ang);
    }

    // Draws on the front layer (hands typically)   
    this.drawPathFr = function (path, fill, ang) {
        ctx.save();
        ctx.rotate(ang * 0.017453); // Math.PI / 180.0);
        ctx.beginPath();
        ctx.moveTo(path[0][0], path[0][1]);

        for (i = 1; i < path.length; i++)
        ctx.lineTo(path[i][0], path[i][1]);
        ctx.closePath();
        ctx.fillStyle = fill;
        ctx.fill();
        ctx.restore();
    };

    this.drawPathBk = function (path, fill, ang) {
        back_ctx.save();
        back_ctx.rotate(ang * 0.017453); // Math.PI / 180.0);
        back_ctx.beginPath();
        back_ctx.moveTo(path[0][0], path[0][1]);

        for (i = 1; i < path.length; i++)
        back_ctx.lineTo(path[i][0], path[i][1]);
        back_ctx.closePath();
        back_ctx.fillStyle = fill;
        back_ctx.fill();
        back_ctx.restore();
    };

    /// one time code for the clock

    this.drawBackground();    // create background that usually is static
    
    if (clockOpts.useUTC) dateOpts.useUTC = clockOpts.useUTC;
    
    this.ticker();    // force initial
    this.start();    // start it up by default
} // Clock
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>jsAnalogClock</title>
	  <script type='text/javascript' src='analogclock.js'></script>

</head>

<!-- Working on fixing up the commonly found HTML5 clock -->
<!-- Making it soft first, then create a clock object and related part -->
<!-- (C) Sandy Ganz 2014-2015 [email protected] -->

<body onLoad="runOnLoad();">
	<h1>Javascript Analog Clock Hack by Sandy Ganz</h1>
    <canvas id="analog-clock"></canvas>
    <canvas id="analog-clock1"></canvas>
	<p>
    <a href="http://www.wtfpl.net/"><img
           src="http://www.wtfpl.net/wp-content/uploads/2012/12/wtfpl-badge-4.png"
           width="80" height="15" alt="WTFPL" /></a>
    <p>We Proudly Support WTFPL for licensing</p>       
	<h2>Here is the link to the project so you can mess with the code</h2>
	<a href="http://jsfiddle.net/sganz/t20qv4rt/">jsFiddle Link</a><br />
	<a href="https://github.com/sganz/analogclock.git">GitHub Javascript Repo (More Current then jsFiddle)</a>
	</p>
    <script type="text/javascript">
        function runOnLoad()
        {
            var a1 = myclock1('analog-clock');
            var a2 = myclock2('analog-clock1',
                [{start:"08:00",end:"09:00",subject:"test1"},
                 {start:"10:00",end:"12:30",subject:"test2"},
                 {start:"14:00",end:"16:30",subject:"test3"}],{});
        }
    </script>
</body>

</html>