Displaying The Correct Time For World Cities With AJAX / JavaScript / DOM

Recently asked on Yahoo! Answers:

JavaScript Help?

I’m working on JavaScript, and my assignment is to write a page that when you click on the radio button of a city and click update, it displays the time in the text box. however, its not working – can you help? (i’m on a library computer without admin privledges and without firefox so i can’t debug)

I could have fixed the supplied code but it didn’t make use of certain efficiencies; additionally, I wanted to add some code that would increase the accuracy of the results — such as working from a single date object to compute all time, checking for Daylight Saving Time, etc.

So, without further ado, here’s the code. And, as always, the end of this post includes a link to a working demo, which you can save and use yourself.

Step 1: The XHTML Form

Our form is some simple radio buttons that share a common name and all have an onclick event that points to a JavaScript function we’ll discuss shortly.

I used onclick because if you use onchange, Internet Explorer will show the results of the last click, not the current click (don’t even get me started on a tirade about that).

We also have a DIV that will display the time the user selects. This could easily be changed to a textbox, as the questioner states he is using.

Select a city:

Step 2: Some Supporting Functions

Before I get into the JavaScript that will display the chosen city time, I want to review some helper functions we need to make this script sing. First up is a simple script that figures out if we are in Daylight Saving Time.

In the United States (and most of the world that observes DST), Daylight Saving Time now begins on the second Sunday of March and ends on the first Sunday of November, in both cases at 2 a.m. So, all we need to do is construct those two dates, then figure out if the current date falls between those two dates. If it does, we’re in Daylight Saving Time; if it doesn’t, we’re not.

So, our function will either add one hour to our timezone offset, or return the same timezone offset we supplied as an argument (“Spring forward, fall back”).

function offsetDST(somehour) {
	var now = new Date();
	var startDate = new Date();
	var endDate = new Date();

	//construct daylight saving start date
	startDate.setMonth(2);
	startDate.setDate(1);
	startDate.setHours(1);
	startDate.setMinutes(0);
	startDate.setSeconds(0);
	var startDay = startDate.getDay();
	if(startDay > 0) {
		startDay = 15 - startDay;
	}
	else {
		startDay = 8;
	}
	startDate.setDate(startDay);

	//construct daylight saving end date
	endDate.setMonth(10);
	endDate.setDate(1);
	endDate.setHours(1);
	endDate.setMinutes(0);
	endDate.setSeconds(0);
	var endDay = endDate.getDay();
	if(endDay > 0) {
		endDay = 8 - endDay;
		endDate.setDate(endDay);
	}

	//if we're in daylight time, add one hour to offset
	if(now > startDate && now < endDate) {
		somehour += 1;
	}

	return somehour;
}

Next up are two functions that will return string values for weekday or month integer arguments, respectively.

function getDayString(dayint) {
	var output;
	switch(dayint) {
		case 0:
			output = "Sunday";
			break;
		case 1:
			output = "Monday";
			break;
		case 2:
			output = "Tuesday";
			break;
		case 3:
			output = "Wednesday";
			break;
		case 4:
			output = "Thursday";
			break;
		case 5:
			output = "Friday";
			break;
		case 6:
			output = "Saturday";
			break;
	}

	return output;
}

function getMonthString(monthint) {
	var output;
	switch(monthint) {
		case 0:
			output = "January";
			break;
		case 1:
			output = "February";
			break;
		case 2:
			output = "March";
			break;
		case 3:
			output = "April";
			break;
		case 4:
			output = "May";
			break;
		case 5:
			output = "June";
			break;
		case 6:
			output = "July";
			break;
		case 7:
			output = "August";
			break;
		case 8:
			output = "September";
			break;
		case 9:
			output = "October";
			break;
		case 10:
			output = "November";
			break;
		case 11:
			output = "December";
			break;
	}
	return output;
}

Finally, we have three functions which will help us format the hour of the day: one that sets the proper 12-hour part from the 24-hour part JavaScript will give us; another that will pad single-digit values; and finally, one that figures out if it's AM or PM.

function getHour(hourint) {
	if(hourint == 0) {
		return 12;
	}
	else if(hourint > 12) {
		return hourint - 12;
	}
	else {
		return hourint;
	}
}

function getDayPart(hourint) {
	if(hourint < 12) {
		return "a.m.";
	}
	else {
		return "p.m.";
	}
}

function padTime(someint) {
	if(someint < 10)  {
		someint = "0" + someint;
	}
	return someint;
}

Step 3: The getCityTime() Function

At long last, we can get into the function that displays the selected city's time. To begin, we need to declare some variables:

  • theCities will get all the checkboxes from our form, using the getElementsByName method;
  • theDiv will reference the DIV we use to display the selected city time;
  • selectedCity will be the city chosen from the radio buttons;
  • theOffset is the time zone offset from UTC time of the selected city;
  • theMilliseconds is the number of milliseconds in the current timestamp;
  • outputString is the string we will output into the theDiv;
  • theTime is a Date variable we use to figure the time for the selected city;
  • utcMilliseconds will hold the UTC timestamp for the current date.
function getCityTime() {
	var theCities = document.getElementsByName('theCity');
	var theDiv = document.getElementById('showTime');
	var selectedCity = "";
	var theOffset = 0;
	var theMilliseconds = 0;
	var outputString = "";
	var theTime = new Date();
	var utcMilliseconds = Date.UTC(theTime.getUTCFullYear(),theTime.getUTCMonth(),theTime.getUTCDate(),theTime.getUTCHours(),theTime.getUTCMinutes(),theTime.getUTCSeconds(),theTime.getUTCMilliseconds())

With the variables out of the way, we need to figure out which radio button is selected. As we've noted before, getElementsByName() returns an array of all elements on a page that share the same name attribute -- in this case, all the radio buttons named theCity.

We can then iterate through all those radio buttons, finding the one that is checked, and assign the value of that radio button to the selectedCity variable.


	for(var i = 0; i < theCities.length; i++) {
		if(theCities[i].checked) {
			selectedCity = theCities[i].value;
			break;
		}
	}

The reason we've gone to the trouble of having a selectedCity variable that we instantiated as empty is because we want to only display something in the theDiv if we have good data.

So, we check if our array walk that we just created has resulted in a value. If so, we set theOffset to an appropriate number (using our offsetDST() function to help, where appropriate). If selectedCity doesn't match one of our approved values, we set selectedCity to be blank. (This is me being anal. It's really not needed.)


	if(selectedCity != "") {
		switch(selectedCity) {
			case "London":
				theOffset = 0;
				break;
			case "New York":
				theOffset = offsetDST(-5);
				break;
			case "San Fransisco":
				theOffset = offsetDST(-9);
				break;
			case "Tokyo":
				theOffset = 9;
				break;
			default:
				selectedCity = "";
		}
	}

We'll now prepare the timestamp we intend to display. First, we check, once again, if selectedCity is set. If not, we clear theDiv.

If yes, we "add" to our timestamp theOffset times the number of milliseconds in an hour -- namely, 3.6 million. Notice that adding a negative number, which most US cities have from UTC, has the same effect as subtracting a positive number (yes, I recall 5th grade math very well).


	if(selectedCity == "") {
		theDiv.innerHTML = "";
	}
	else {
		theMilliseconds = (theOffset * 3600000);
		theMilliseconds += utcMilliseconds;
		theTime.setTime(theMilliseconds);

Now we output the result. Unfortunately, JavaScript's built-in toString() functions for dates are awful; if we try to use toString(), toLocaleString() or toUTCString(), all three will manipulate our timestamp to the wrong time. So, we have to go through all the rigamarole below to get a decent, formatted string.


		outputString = "

The current time in " + selectedCity + " is " + getDayString(theTime.getUTCDay()) + ", " + getMonthString(theTime.getUTCMonth()) + " " + padTime(theTime.getUTCDate()) + ", " + theTime.getUTCFullYear() + " " + padTime(getHour(theTime.getUTCHours())) + ":" + padTime(theTime.getUTCMinutes()) + ":" + padTime(theTime.getUTCSeconds()) + " " + getDayPart(theTime.getUTCHours()) + "

"; theDiv.innerHTML = outputString; } }

And that's it. You can see a working demo of this code here: http://www.dougv.com/demo/js_city_time/.

I distribute code under the GNU GPL version 3.

One thought on “Displaying The Correct Time For World Cities With AJAX / JavaScript / DOM

Leave a Reply