Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at the New York ColdFusion User Group (Feb. 2008) with: Peter Bell

Converting To And From GMT / UTC Time In ColdFusion Using DateConvert()

By Ben Nadel on
Tags: ColdFusion

A few days ago, I started looking into using GMT (Greenwich Mean Time) and UTC (Universal Time Coordinated) times in ColdFusion. Specifically, I was looking into creating HTTP headers that required time to be sent in a special GMT-based HTTP time format. As I posted yesterday, I could easily get HTTP time stamps using GetHTTPTimeString(); this ColdFusion method would automatically convert from local time to GMT time and then format the date/time value for use with HTTP headers. I also demonstrated that you could use DateAdd() to convert to and from UTC time as well.

In the comments to my post yesterday, John Piotrowski pointed out that my DateAdd() calculations could be even more easily done with ColdFusion's DateConvert() method. From the documentation, DateConvert() takes a conversion type (Local2UTC / UTC2Local) and a date/time stamp. To make sure that this was an equivalent short-hand to DateAdd(), I ran a few quick tests:

  • <!--- Get the current time. --->
  • <cfset dtNow = Now() />
  •  
  • <!---
  • Convert the date to GMT using DateAdd() and DateConvert()
  • to make sure that they are the same.
  • --->
  • DateAdd(): #DateAdd( "s", GetTimeZoneInfo().UTCTotalOffset, dtNow )#
  • <br />
  •  
  • DateConvert(): #DateConvert( "Local2UTC", dtNow )#
  • <br />

I this test, I am comparing DateAdd() and DateConvert() when converting the local time to UTC time. When I run the above code, I get the following output:

DateAdd(): {ts '2009-05-27 13:13:59'}
DateConvert(): {ts '2009-05-27 13:13:59'}

Exactly the same. Now, this is probably not needed at all, but I ran a test in the opposite direction as well just to make sure all was right with the world:

  • <!--- Get the GMT time. --->
  • <cfset dtGMT = ParseDateTime(
  • GetHTTPTimeString( Now() )
  • ) />
  •  
  • <!--- Convert from GTM back to local time. --->
  • Now: #Now()#
  • <br />
  •  
  • DateConvert(): #DateConvert( "UTC2Local", dtGMT )#
  • <br />

When I run the above code I get the following output:

Now: {ts '2009-05-27 09:13:59'}
DateConvert(): {ts '2009-05-27 09:13:59'}

As you can see from the above demonstrations, DateConvert() is an effective shorthand for the combination of DateAdd() and GetTimeZoneInfo(). Thanks John Piotrowski, you rock!




Reader Comments

Hello, Your blogs are really helpful. I noticed one thing working with date conversion. May be you can help me fix it. I converted 11/06/2010 19:00:00 and it converts to 2010-11-07 01:00:00.0000 whereas it should be 2010-11-07 02:00:00.0000. This is happening to all dates where time is 19:00 to midnight on 11/6/2010. Have you encountered this problem? If yes, have you been able to find a fix?

Reply to this Comment

@Ben,

We talked to someone at Adobe and they informed us that it is a bug in CFMX 7. Sorry I forgot to mention the CF version. We will have to put a fix for that timeframe. Thanks for taking time to respond. :)

Reply to this Comment

@PShah,
Sorry to dig up an old comment thread, but is that DateConvert() bug documented anywhere? I'm running into something similar (the discrepancy is an added hour rather than a subtracted hour and it occurs in the spring, not fall), but I only see it on CF8 and CF9, not CF7. I'm planning to submit a report to cfbugs. I haven't seen any previous reports about DateConvert() there or anything in "Known Issues", so I don't think I'm submitting a duplicate. What did you end up doing for a workaround?

Thanks!

Reply to this Comment

@LX,

I ended up using Java objects to get the correct date/time. But it would work only if you do not use coldfusion date/time functions once you have the correct date time from the Java object. Following is the function that we use. It was provided by Adobe and is designed basically to return a string in whatever format you need. In our case it is 'yyyy-mm-ddTHH:mm:ss.0000Z' or 'mm/dd/yyyy HH:mm:ss'. Hope this helps you.

<cffunction name="DateConvertNoBug" output="true" returntype="string">
<!---
This function returns a string in a very specific format; it does NOT return ColdFusion Date/Time values.
This function is NOT a replacement for the built-in DateConvert function, which returns ColdFusion Date/Time values.
DateConvert in CFMX and CFMX 7 has a bug that causes it to do wrong conversions around the time of Daylight Savings
Time (DST) changes. DateConvert in ColdFusion 9 (and probably ColdFusion 8) has a different bug that causes it to do
wrong conversions around the time of DST changes. This function uses only Java to do Date/Time conversions;
it does NOT make use of any ColdFusion Date/Time functions and so is not subject to any bugs in ColdFusion Date/Time
functions. For proper results to be generated, this function relies on Java being aware of the proper dates on which DST
changes take effect (for more info, see http://www.java.com/en/download/faq/dst.xml).
--->

<!---
Same arguments as DateConvert (names may be slightly different but this doesn't
matter since calling code doesn't reference the names.)
--->
<cfargument name="conversionType" type="string" required="true">
<cfargument name="dateTimeToConvert" type="date" required="true">

<!---Initialize variables with dummy data.--->
<cfset var errorMessage = "">
<cfset var monthForDateTimeToConvert = 0>
<cfset var convertedYear = 0>
<cfset var convertedMonth = 0>
<cfset var convertedDay = 0>
<cfset var convertedHour = 0>
<cfset var convertedMinute = 0>
<cfset var convertedSecond = 0>
<cfset var javaDateTimeToConvert = 0>
<cfset var javaDateTimeConverter = 0>
<cfset var javaDateTimeConverted = 0>

<!---
The only 2 valid values for Arguments.conversionType are local2Utc and utc2Local, as is true for DateConvert.
Throw error (basically the same as that thrown by DateConvert) if a different value is supplied.
--->
<cfif Arguments.conversionType NEQ "local2Utc" AND Arguments.conversionType NEQ "utc2Local">
<cfset errorMessage = Arguments.conversionType & " is an invalid conversion type for the DateConvertNoBug function.">
<cfthrow message="#errorMessage#">
</cfif>

<!---Convert the time to/from UTC.--->
<cfif Arguments.conversionType EQ "local2Utc">
<!---Initialize variables.--->
<cfset javaDateTimeToConvert = CreateObject("java", "java.util.GregorianCalendar")>
<cfset javaDateTimeConverter = CreateObject("java", "java.util.GregorianCalendar").getInstance(CreateObject("java", "java.util.TimeZone").getTimeZone("GMT"))>
<cfelse>
<!---Initialize variables.--->
<cfset javaDateTimeToConvert = CreateObject("java", "java.util.GregorianCalendar").getInstance(CreateObject("java", "java.util.TimeZone").getTimeZone("GMT"))>
<cfset javaDateTimeConverter = CreateObject("java", "java.util.GregorianCalendar")>
</cfif>

<!---Set the date/time to convert.--->
<cfset monthForDateTimeToConvert = Month(Arguments.dateTimeToConvert) - 1>

<cfset javaDateTimeToConvert.set(JavaCast("int", Year(Arguments.dateTimeToConvert)), JavaCast("int", monthForDateTimeToConvert), JavaCast("int", Day(Arguments.dateTimeToConvert)), JavaCast("int", Hour(Arguments.dateTimeToConvert)), JavaCast("int", Minute(Arguments.dateTimeToConvert)), JavaCast("int", Second(Arguments.dateTimeToConvert)))>

<!---Convert the individual parts of the date/time.--->
<cfset javaDateTimeConverter.setTimeInMillis(javaDateTimeToConvert.getTimeInMillis())>
<cfset convertedYear = javaDateTimeConverter.get(javaDateTimeToConvert.YEAR)>
<cfset convertedMonth = javaDateTimeConverter.get(javaDateTimeToConvert.MONTH)>
<cfset convertedDayOfMonth = javaDateTimeConverter.get(javaDateTimeToConvert.DAY_OF_MONTH)>
<cfset convertedHourOfDay = javaDateTimeConverter.get(javaDateTimeToConvert.HOUR_OF_DAY)>
<cfset convertedMinute = javaDateTimeConverter.get(javaDateTimeToConvert.MINUTE)>
<cfset convertedSecond = javaDateTimeConverter.get(javaDateTimeToConvert.SECOND)>
<cfset javaDateTimeConverter.set(convertedYear, convertedMonth, convertedDayOfMonth,
convertedHourOfDay, convertedMinute, convertedSecond)>

<cfif lcase(conversionType) eq "local2utc">
<cfset convertedStr = NumberFormat(convertedYear, "0000") & "-" & NumberFormat(convertedMonth + 1, "00") & "-" & NumberFormat(convertedDayOfMonth, "00") & "T" & NumberFormat(convertedHourOfDay, "00") & ":" & NumberFormat(convertedMinute, "00") & ":" & NumberFormat(convertedSecond, "00") & ".0000Z">
<cfelse>
<cfset convertedStr = NumberFormat(convertedMonth + 1, "00") & "/" & NumberFormat(convertedDayOfMonth, "00") & "/" & NumberFormat(convertedYear, "0000") & " " & NumberFormat(convertedHourOfDay, "00") & ":" & NumberFormat(convertedMinute, "00") & ":" & NumberFormat(convertedSecond, "00")>
</cfif>


<!---Return the converted date/time string.--->
<cfreturn convertedStr>
</cffunction>

Reply to this Comment

Hello there,

We want to save client datetime to the server. We have created a Flex application which sends data to coldfusion. The datatime is converted to coldfusion server datatime when data is received by coldfusion. Is there a way to preserve the original datetime send from client.

Thanks for d help.
Shiv

Reply to this Comment

@Shivam,

I don't deal with localization very much; but, I suppose you could store two points of data - the UTC date/time and the user's timezone. Then, you can always convert back and forth between the UTC time and given user's "post time" while at the same time, keeping a normalized timestamp in the database.

I think???

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.