Coldfusion 10, ISO 8601 dates, and bugs

JavaScript generates an ISO 8601 date like this:

new Date();
// returns Mon Oct 08 2018 11:17:34 GMT+1100 (Australian Eastern Daylight Time)

new Date().toISOString();
// returns "2018-10-08T00:17:34.004Z"

Note the inclusion of milliseconds and the conversion to the UTC time.

If you want to use that date string in parseDateTime() in ColdFusion 10 (and maybe later versions but not tested by me), you need to specify the correct mask. The CF docs seem to be unclear regarding the milliseconds. This is what seems to work:

// ISO 8601 date from JS in UTC

dtStr = "2018-10-08T00:17:34.004Z";

res = parseDateTime(dtStr,"yyyy-MM-dd'T'HH:mm:ss.SSSX");

dateTimeFormat(res, "yyyy-mm-dd hh:nn:ss.LLL z");
// returns: 2018-10-08 11:17:34.004 EST

res = parseDateTime(dtStr,"yyyy-MM-dd'T'HH:mm:ss.SSS");
res = parseDateTime(dtStr,"yyyy-MM-dd'T'HH:mm:ss.SS");
res = parseDateTime(dtStr,"yyyy-MM-dd'T'HH:mm:ss.S");

// For all the above,
dateTimeFormat(res, "yyyy-mm-dd hh:nn:ss.LLL z");
// returns: 2018-10-08 12:17:34.000 EST <== note 12:17, not 11:17 as above

The CF date object created by parseDateTime() uses the time zone of the CF server it is running on. ie converts UTC to local (server) time as long as you specify the ‘X’ in the mask.

1. the 'T' in the mask – the single quotes are required or an error will be thrown.

2. the mask for the ms when passed to parseDateTime is ‘S’ NOT ‘L’ (as it is for timeFormat() and dateTimeFormat

3. the final X is required to maintain UTC adjustments and you must also have the same number of digits in the ms part.
ie: if the date string ms is three digits (eg “.004Z”) the mask must also be three digits (ie “.SSSX”).
“.SSX” or “.SX” etc will throw errors if the mask is three digits.

4. Time Zone bug: Today (Oct 8th) is in daylight saving time. If I dump out getTimeZoneInfo(), the utcHourOffset is correct at -11. But notice that the time zone displayed is EST. It should be AEDT (Australian Eastern Daylight Time). If I use a test date before DST (eg Oct 1st) it still says EST when it should say AEST (Australian Eastern Standard Time).

5. Daylight Saving Time: the test date here (Oct 8th) converts accounting for DST as long as I specify the “X” in the mask. If I use a test date NOT in DST (eg Oct 1st) it correctly converts the time to 2018-10-01 10:17:34.004 EST ie 10am, not 11am.

Note I am using the dateTimeFormat() function, not timeFormat(). Despite what the docs say, the ‘z’ mask does not work as expected.

dateTimeFormat(res, "yyyy-mm-dd hh:nn:ss.LLL z");
// returns: 2018-10-08 11:17:34.000 EST 
// but 
timeFormat(res,"hh:nn:ss.LLL z");
// returns 2018-10-08 11:17:34.004 z  <== ie literal z

Using quotes around ‘z’ makes no difference.

See also:


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s