Making a set of timezone clocks using PHP, jQuery and CSS3

August 21, 2011

Here is how to build a set of timezone clocks using PHP, jQuery and CSS3. It’s based heavily on Toby Pitman’s example, and even uses his images. I’ve added the extra timezones using a PHP array. In theory it would be possible to do it all in Javascript, but PHP is good at handling dates, and there’s no need to do any horrible maths with timezone offsets. Just tell the server which timezone you are interested in. I’ve also changed the original javascript to deal with more than one clock on a page, and to show a digital clock as well. Of course, it won’t work in Internet Explorer 8 or below, but then again I believe that we shouldn’t be trying to make websites look the same in every browser. If you really need a cross-browser version, you could do it using CSS sandpaper. First, set up your clocks. Build an array of time zones, and then loop through it, setting the server timezone using date_default_timezone_set() as you go. See the PHP site for the full list of supported timezones. I’ve used an associative array, just so that I can output the city name rather than the timezone identifier.

$timezones = array(
  'UTC' => 'GMT',
  'America/Los_Angeles' => 'Los Angeles',
  'America/New_York' => 'New York',
  'Europe/London' => 'London',
  'Europe/Paris' => 'Paris',
  'Europe/Moscow' => 'Moscow',
  'Asia/Tokyo' => 'Tokyo',
  'Australia/Sydney' => 'Sydney'
);

foreach ($timezones as $timezone => $name) {
    date_default_timezone_set($timezone);
    ?>
  <div class="clock-wrapper">
    <h2><?php echo $name; ?></h2>
    <ul class="clock" id="<?php echo strtolower(str_replace(' ', '-', $name)); ?>" 
      hours="<?php echo date('H'); ?>" minutes="<?php echo date('i'); ?>">	
      <li class="sec"></li>
      <li class="hour"></li>
      <li class="min"></li>
      <li class="digital"><?php echo date('H:i:s'); ?></li>
      <?php 
        // daylight savings time?
        if(date('I')) {
          echo '<li class="DST"><a href="http://www.worldtimezone.com/daylight.html" title="Daylight Savings Time">DST</a></li>';
        }
      ?>
    </ul>
  </div>
<?php
}
?>

Here’s the basic CSS:

#block-red-clocks {
  overflow: auto;
}

.clock-wrapper {
    width: 170px;
    float: left;
}

.clock-wrapper h2 {
    text-align: center;
    margin: 0;
}

.clock {
    position: relative;
    width: 150px;
    height: 175px;
    margin: 0 auto 20px auto;
    background: url(/sites/all/modules/custom/red/clocks/images/clockface.jpg) no-repeat;
    list-style: none;
    padding: 0;
}

.digital {
    bottom: 0;
    font-size: 12px;
    font-weight: bold;
    position: absolute;
    text-align: center;   
    width: 100%;
}

.DST {
	position: absolute;
	bottom: 0;
	right: 0;
	font-size: 10px;
}

.DST a {
	font-weight: normal;
}

.sec, 
.min, 
.hour {
    position: absolute;
    width: 8px;
    height: 150px;
    top: 0px;
    left: 72px;
}

.sec {
    background: url(/sites/all/modules/custom/red/clocks/images/sechand.png) no-repeat;
    z-index: 3;
}

.min {
    background: url(/sites/all/modules/custom/red/clocks/images/minhand.png) no-repeat;
    z-index: 2;
}

.hour {
    background: url(/sites/all/modules/custom/red/clocks/images/hourhand.png);
    z-index: 1;
}

By setting the time as attributes of the clock element, it’s easy to get the hours and minutes separately for each clock using jQuery. Apart from that change, the rest of the javascript is more or less the same as Toby Pitman’s original, just with the movement put into a function so as to be able to animate each clock.

$(document).ready(function() {

    function rotateHands(clock, time) {
      // advance the time by one second
      time.setTime(time.getTime()+1000, 0);
                        
      // get the time components
      var seconds = time.getSeconds();
      var hours = time.getHours();
      var mins = time.getMinutes();
                        
      // work out the angle for each clock hand                 
      var sdegree = seconds * 6;
      var srotate = "rotate(" + sdegree + "deg)";
        
      var mdegree = mins * 6;
      var mrotate = "rotate(" + mdegree + "deg)";
        
      var hdegree = hours * 30 + (mins / 2);
      var hrotate = "rotate(" + hdegree + "deg)";
                        
      // change the CSS to move the hands
      $(clock).find(".sec").css({
        "-moz-transform" : srotate, 
        "-webkit-transform" : srotate
      });
      $(clock).find(".hour").css({
        "-moz-transform" : hrotate, 
        "-webkit-transform" : hrotate
      });
      $(clock).find(".min").css({
        "-moz-transform" : mrotate, 
        "-webkit-transform" : mrotate
      });
                    
      // set the digital time, adding leading zeros if necessary
      $(clock).find('.digital').html(
        time.getHours() + ':' + 
        (time.getMinutes() < 10 ? '0': '') + time.getMinutes() + ':' +
        (time.getSeconds() < 10 ? '0': '') + time.getSeconds());
    }
            
    $('.clock').each(function(){
      var clock = this;
        
      // get the current system time
      var time = new Date();
        
      // set the time according to its attributes
      time = new Date(time.getFullYear(), time.getMonth(), time.getDate(), $(this).attr('hours'),$(this).attr('minutes'), time.getSeconds());
                    
      // move the hands every second
      setInterval( function() {
        rotateHands(clock, time);
      }, 1000 );
        
    }); 
  });