ColdFusion in Context: Greenwich Mean Time (GMT)

You may have noticed that HTTP header dates are returned in GMT (as required by RFC 2616) instead of in local time. In order to generate your own header dates, you need to be able to convert local time to GMT. The conversion isn't just in whole hours. Local time is Kabul, Afghanistan is GMT + 4:30. In Kathmandu, Nepal, it's GMT + 5:45. In Adelade, Australia, it's GMT + 10:30 during daylight savings time in the summer, which occurs when the northern hemisphere has its winter. You can determine GMT for your Web server; here's how.

Support

Sometimes you get more information than you need when trying to solve a problem, and the extra information simply confuses the issue instead of clarifying it. Determining GMT from local time is this kind of problem, and many published solutions to this problem miss the point. When you set a ColdFusion variable, say, MyZone, equal to getTimeZoneInfo(), you can obtain the following pieces of information:
  1. MyZone.utcTotalOffset provides the number of *SECONDS* that need to be added to the local time to get GMT. The documentation says this is the number of minutes, but if you do the math for your time zone, you'll see that the offset is indeed in seconds.
  2. MyZone.utcHourOffset provides the offset in whole hours.
  3. Adding MyZone.utcMinuteOffset to MyZone.utcHourOffset provides the offset in hours and minutes.
  4. MyZone.isDSTOn is true if Daylight Savings Time is in effect on the host server. (Otherwise, it's false.)
It turns out (contrary to some examples) that you only need the first piece of information. If you flop your server back and forth between a month where Daylight Savings Time is in effect where you live and a month where it it isn't (assuming that you ever use Daylight Savings Time where you live), MyZone.isDSTOn turns on and off, but MyZone.utcTotalOffset also changes. Because MyZone.utcTotalOffset already changes when Daylight Savings Time changes, you don't need to know whether Daylight Savings Time is in effect when you do the conversion.

Code

Knowing this, you can create a ColdFusion User-Defined Function to provide a string that expresses local time as the correctly-formatted GMT equivalent for HTTP headers. Use the getTimeZoneInfo function. Get the current local date/time. Add the total offset in seconds to the local time. The dateAdd function handles this when you tell it the units to use (e.g., 's' for seconds). Finally, format the date and time portions separately and combine the resulting strings to get what you want. The string will begin with the abbreviation for the day of the week, then the complete date, then the time (including seconds), and then the letters "GMT". You'll specify 'ddd' to get the three-letter english abbreviation for the day of the week - it must be in english - 'dd' to get the day of the month with leading digits; 'mmm' to get the three-letter month in english; 'yyyy' to get the four-digit year; 'HH' to get hours in a 24-hour clock with leading digits (lower case 'hh' would have provided a 12-hour clock); 'mm' to get minutes with leading digits; and 'ss' to get seconds with leading digits.

<cfscript>
function GMT(){
  // Gets GMT date/time (GMT) from local time
  TZ=getTimeZoneInfo();
  DT=now();
  GDT=dateAdd('s',TZ.utcTotalOffset,DT);
  GMTDt=DateFormat(GDT,'ddd, dd mmm yyyy');
  GMTTm=TimeFormat(GDT,'HH:mm:ss');
  GMT="#GMTDt# #GMTTm# GMT";
}
</cfscript>

Experiment

To see this in action, save the GMT function description above to zone.cfm, then add the following code to the current GMT date/time stamp followed by a list of offsets for you to learn from. Use the iif (instant if) and de (delay evaluation) functions to readily convert true and false to on and off values for display.

GMT time is...<br>
<cfoutput>#GMT()#</cfoutput>
<p>
<cfset TZ1=getTimeZoneInfo()>
<cfoutput>
Offset in whole hours is #TZ1.utcHourOffset#<br>
Additional offset in minutes is #TZ1.utcMinuteOffset#<br>
Total offset in seconds is #TZ1.utcTotalOffset#<br>
Local Daylight Savings Time is #iif(TZ1.isDSTon,de("on"),de("off"))#<br>
</cfoutput>

Browse zone.cfm. If you don't see the current GMT date and time followed by a list of offsets, you've probably forgotten to paste the GMT function into the top of the page.

Consider

Notice that you don't need the TZ1 code above for a real application. You only need the script for the GMT() function and a cfoutput statement that contains GMT() in pound signs. So what can you do with this? Remember that ColdFusion lets you set HTTP headers to modify the manner in which pages are retrieved, and some of these headers require GMT dates. Also, an understanding of time adjustments will help you when the boss wants you to schedule teleconferences among multiple cities. Try this function out, and then tell us what you've learned. =Marty=