To mimic the naming and behavior of the getHttpTimeString() function, I created a user-defined function (UDF) called getIsoTimeString(). This function takes your date/time object and returns the ISO time string using the UTC timezone. Unless otherwise flagged, the getIsoTimeString() will assume your date/time object is in server-local time and convert it to UTC before formatting it:

<cfscript>

// I take the given date/time object and return the string that

// reprsents the date/time using the ISO 8601 format standard.

// The returned value is always in the context of UTC and therefore

// uses the special UTC designator ("Z"). The function will

// implicitly convert your date/time object to UTC (as part of

// the formatting) unless you explicitly ask it not to.

string function getIsoTimeString(

required date datetime,

boolean convertToUTC = true

) {

if ( convertToUTC ) {

datetime = dateConvert( "local2utc", datetime );

}

// When formatting the time, make sure to use "HH" so that the

// time is formatted using 24-hour time.

return(

dateFormat( datetime, "yyyy-mm-dd" ) &

"T" &

timeFormat( datetime, "HH:mm:ss" ) &

"Z"

);

}

// ------------------------------------------------------ //

// ------------------------------------------------------ //

currentTime = now();

// Compare the HTTP time to the ISO time.

writeOutput( "HTTP Time: " & getHttpTimeString( currentTime ) );

writeOutput( "<br />" );

writeOutput( "ISO Time: " & getIsoTimeString( currentTime ) );

</cfscript>

When we run the above code, we get the following HTTP and ISO time formats:

Reader Comments

You might test to ensure that dateConvert() is accounting for DST correctly. I have found in the past (at least as recently as CF8,) that dateConvert() applies the DST offset based on the DST offset of the current date and time...not the actual offset for date and time submitted to the function.

Example: Now() is Jul. 29 @ 2:00pm EDT. Make sure that if you submit a datetime NOT in the local DST range (say Nov. 4 @ 2:00pm EST) that convertDate() doesn't try to use the current local DST offset when it does the conversion.

I have written a fairly elaborate dateTime conversion function that first determines whether DST applies for the dateTime passed (based on the timezone and DST rules for locality in question,) then does the conversion taking into account that info.

I recently updated some code Constant Contact's API v2. In scheduling an email, I provide a ISO 8601 date. Although I believe the standard makes it optional, the API required the trailing decimals on the seconds. I just hardcoded ".000" to get:

I've been meaning to standardize my date/times in my application. Currently, I just "know" my servers are in CST so I account for that in code, but I would love to use UTC as a standard and base all calculations off that. Is there an easy way to determine the local timezone offset so that the ISO 8601 date can be converted to local time?

@David, would a copy of that more elaborate function happen to be available somewhere? I'm in a position where an application is going to switch from using a single timezone to UTC and we have several years of old data that will need to be converted back from local time to UTC but will need to take the former time zones into account as well.

Very interesting. I had thought that UTC time didn't take Daylight Saving Time (DST) into account. I thought that that was part of the reason everyone converts to it for inter-service communication - that's its always standard. That said, "timezone hell" is called "hell" for a reason :(

At InVision, we do a lot of JavaScript-oriented work with loads of API calls to the server (basically we have a few single-page apps (SPAs)). We recently starting asking the Browser to report its local timezone offset when communicating to the server. We use the timezone offset in the Date object:

We had to deal with that a few months ago. "Luckily" all our dates were in EST to begin with, so no one but east-coasters had accurate time anyway. That made the conversion much easier :D We simply converted all EST time to UTC time.

Good luck with your conversion. It definitely makes some things easier and some things harder (to think about).

Correct, UTC itself is not affected by DST, but since local time is (or can be,) it still matters whenever you are converting from one to the other. (Example: EST is UTC -5, but EDT is UTC -4.) We store everything in UTC wherever possible, but some clients prefer to see time stamps in their local time. So the only time we really have to worry about it is during output / display.

@Justin,

If I can find the function in question and sanitize it a bit, I'd be happy to share.

Ah gotcha - I see what you mean. Yeah, we've run into that a bit, for sure. Like I was saying in an earlier comment to Chris, we store the timezone offset defined by the browser; honestly, I have no idea if that takes DST into account... and, even if it does, there's no saying that it's accurate at the time we go to use it ... heck if the user was in a hotel one day in one timezone, the computer may have automatically updated and then the next time we go to send an email, we'd be off.

That said, we do try to render the date/times on the client-side as much as possible. To do that, we pass the date/time values (over AJAX) as UTC milliseconds. Then, on the client, we let the browser convert that into a local Date object (pseudo code):

// CreatedAt is passed as UTC-milliseconds.

var date = new Date( response.createdAt );

something.dateLabel = formatDate( date );

This way, at least we pass the burden of proper timezone calculations to the client.

Of course, that is ONLY when we deal with the browser. When we send out an email, things definitely get a bit more fuzzy :)

Very interesting. I like the idea of storing the offset with the user's profile for later use, though you could also let them choose as well.

As for the negation of the offset, I'm lost. Isn't the offset already related to UTC? For instance UTC-8:00 is PST (California for instance) whereas UTC+8:00 would be somewhere in Taiwan. If you negate it, wouldn't that reverse them (two negatives make a positive)?

I imagine that if the stored offset differs from the injected offset, you go with the injected offset and update the stored value?

The negation of the timezone offset is a strange thing and it took me a while to wrap my head around. The problem is that we're not using the offset to get from LOCAL time to UTC time; instead, we're using the offset to get from UTC time (stored in the database) to the user's LOCAL time.

So, I'm in the EST timezone, which is currently (according to my browser) in GMT-4 time. The "-4" there means that if I add -4 hours to GMT, I can EST.... which is what you are saying.

However, if I get my current timzone offset:

( new Date() ).getTimezoneOffset()

... I get "240" - a positive number. The notion here being that if I ADD 240 to my EST time, I'll get the current UTC time.

But, I don't want to go from EST to UTC - I want to go from UTC to EST. As such, I need to negate the "240" that the browser reported, so that I can get this:

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments

Live in the Now

Oops!

Name:

Email:

( I keep this private )

Website:

Comment:

Subscribe to comments.

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.