Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get DateCompare() to behave in ColdFusion 10?

I'm using CF10 with latest update level on Windows in Pacific Standard Time. I need a datecompare() combination that returns 0 but I cannot get it to behave every since Adobe decided to change the behavior of DateConvert() and DateCompare()

<cfset filePath = getBaseTemplatePath()>
<cfset fileinfo = getFileInfo(filePath)>
<cfset lastModified = fileinfo.lastModified>
<cfset lastModifiedUTC = dateConvert("local2utc", lastModified)>
<cfset lastModifiedUTC2 = dateAdd("s", getTimezoneInfo().UtcTotalOffset, lastModified)>

<cfset lastModifiedHttpTime = getHttpTimeString(lastModified)>
<cfset parseLastModifiedHttpTimeSTD = parseDateTime(lastModifiedHttpTime)>
<cfset parseLastModifiedHttpTimePOP = parseDateTime(lastModifiedHttpTime, "pop")>

<cfoutput>
<pre>
lastModified  (local)        : #datetimeformat(lastModified, 'long')#

lastModifiedUTC              : #datetimeformat(lastModifiedUTC, 'long')#
lastModifiedUTC2             : #datetimeformat(lastModifiedUTC2, 'long')#
datecompareLmUTC             : #dateCompare(lastModifiedUTC, lastModifiedUTC2)#  //wtf

lastModifiedHttpTime         : #lastModifiedHttpTime#
parseLastModifiedHttpTimeSTD : #datetimeformat(parseLastModifiedHttpTimeSTD, 'long')#
parseLastModifiedHttpTimePOP : #datetimeformat(parseLastModifiedHttpTimePOP, 'long')#

I need a datecompare() combination that returns 0
------------------------------------------------
DateCompare(lastModifiedUTC, parseLastModifiedHttpTimePOP) : #DateCompare(lastModifiedUTC, parseLastModifiedHttpTimePOP)#
DateCompare(lastModifiedUTC2, parseLastModifiedHttpTimePOP) : #DateCompare(lastModifiedUTC2, parseLastModifiedHttpTimePOP)#

CF Version                : #server.coldfusion.productVersion#, update level: #server.coldfusion.updatelevel#
</pre>
</cfoutput>

OUTPUT:

lastModified  (local)        : September 11, 2015 7:10:23 PM PDT

lastModifiedUTC              : September 12, 2015 2:10:23 AM UTC
lastModifiedUTC2             : September 15, 2015 4:58:22 PM PDT
datecompareLmUTC             : -1  //wtf

lastModifiedHttpTime         : Sat, 12 Sep 2015 02:10:23 GMT
parseLastModifiedHttpTimeSTD : September 12, 2015 2:10:23 AM PDT
parseLastModifiedHttpTimePOP : September 12, 2015 2:10:23 AM UTC

I need a datecompare() combination that returns 0
------------------------------------------------
DateCompare(lastModifiedUTC, parseLastModifiedHttpTimePOP) : 1
DateCompare(lastModifiedUTC2, parseLastModifiedHttpTimePOP) : 1

CF Version                : 10,0,17,295085, update level: 17

I'm pulling my hair out.

like image 656
Henry Avatar asked Sep 12 '15 02:09

Henry


1 Answers

(Too long for comments)

I did some digging with CF11, based on the blog comments. From what I could tell, the reason the initial comparison fails is that although the first two dates look similar:

// code
lastModifiedUTC    : #DateTimeFormat(lastModifiedUTC, "yyyy-mm-dd HH:nn:ss.L zzz")#
lastModifiedUTC2   : #DateTimeFormat(lastModifiedUTC2, "yyyy-mm-dd HH:nn:ss.L zzz")#
// output
lastModifiedUTC    : 2015-09-13 19:51:46.219 UTC
lastModifiedUTC2   : 2015-09-13 19:51:46.219 PDT

... due to time zone differences, internally the objects represent a different point in time. That is why dateCompare() fails to return 0. (The third comparison fails for the same reason.)

// code
lastModifiedUTC              : #lastModifiedUTC.getTime()#
lastModifiedUTC2             : #lastModifiedUTC2.getTime()#
// output
lastModifiedUTC              : 1442173906219
lastModifiedUTC2             : 1442199106219

Notice if you compare lastModifiedUTC to the original (local) date, it works as expected? Despite the different time zones, both objects still represent the same point in time internally:

// code
dateCompare             : #dateCompare(lastModifiedUTC, lastModified)#  
lastModifiedUTC         : #lastModifiedUTC.getTime()#
lastModified            : #lastModified.getTime()#
lastModifiedUTC         : #DateTimeFormat(lastModifiedUTC, "yyyy-mm-dd HH:nn:ss.L zzz")#
lastModified            : #DateTimeFormat(lastModified, "yyyy-mm-dd HH:nn:ss.L zzz")#

// output
dateCompare             : 0  
lastModifiedUTC         : 1442173906219
lastModified            : 1442173906219
lastModifiedUTC         : 2015-09-13 19:51:46.219 UTC
lastModified            : 2015-09-13 12:51:46.219 PDT

Curiously, the second comparison also fails to return 0, despite the fact that both objects seem to have the same time and time zone. However, if you look at the internal time values the milliseconds differ. The milliseconds of the POP value are always zero. DatePart reports the same result. That sort of makes sense, since the POP date was created by parsing a string which does not contain milliseconds. Yet that does not explain why DateTimeFormat shows the milliseconds as non-zero.

The second comparison fails to return 0 because the two dates have different millisecond values. Unlike the file date, the POP date was created by parsing a string that does not contain milliseconds, so that date part is always zero. Since dateCompare() performs a full comparison (including milliseconds) the two dates are not equal.

// code
lastModifiedUTC                         : #DateTimeFormat(lastModifiedUTC, "yyyy-mm-dd HH:nn:ss.L zzz")#
parseLastModifiedHttpTimePOP            : #DateTimeFormat(parseLastModifiedHttpTimePOP, "yyyy-mm-dd HH:nn:ss.L zzz")#
lastModifiedUTC                         : #lastModifiedUTC.getTime()#
parseLastModifiedHttpTimePOP            : #parseLastModifiedHttpTimePOP.getTime()#
datePart(lastModifiedUTC)               : #datePart("l", lastModifiedUTC)#
datePart(parseLastModifiedHttpTimePOP)  : #datePart("l", parseLastModifiedHttpTimePOP)#

// output
lastModifiedUTC                         : 2015-09-13 19:51:46.219 UTC
parseLastModifiedHttpTimePOP            : 2015-09-13 19:51:46.0   UTC
lastModifiedUTC                         : 1442173906219
parseLastModifiedHttpTimePOP            : 1442173906000
datePart(lastModifiedUTC)               : 219
datePart(parseLastModifiedHttpTimePOP)  : 0

However, on a good note, that means the comparison works if you skip the milliseconds and only compare down to the "second" ie dateCompare(date1, date2, "s"):

// code
DateCompare(lastModifiedUTC, parseLastModifiedHttpTimePOP, "s") : #DateCompare(lastModifiedUTC, parseLastModifiedHttpTimePOP, "s")#
// output
DateCompare(lastModifiedUTC, parseLastModifiedHttpTimePOP, "s") : 0

As an aside, I am not sure why Adobe chose to change the behavior of something as critical as UTC dates .. Unfortunately, I do not know that there is much you can do about it other than the options mentioned in the blog comments a) Change the jvm time zone or b) create your own version of dateConvert and use that instead.

Boy what a mess....

like image 145
Leigh Avatar answered Oct 18 '22 20:10

Leigh