简体   繁体   中英

ColdFusion coercion of variables not clear

<cfset academic_year = "2012-13">
<cfoutput># academic_year gt "2009-10" #</cfoutput>

OUTPUTS NO

but if I change academic_year VARIABLE to "2011-12" the Output is YES.

How is ColdFusion coercing the variable academic year?

Just a guess. Perhaps "2011-12" and "2009-10" are being treated as a date with just year and month, so Dec 2011 is greater than Oct 2009. "2012-13" is not being treated as a date because its not a valid month.

What does a cfdump on academic_year show you?

This is probably not the answer you are looking for, but I would STRONGLY suggest that if you're going to compare dates that you do one of two things:

  1. Use the datecompare() function.
  2. Use parseDateTime() as Railo suggests in their compatibility guide .

It will save you from a lot of headaches like this and make life easier.

You're doing a comparison of two strings that look like "yyyy-mm" dates, but are in fact "yyyy-yy" strings. You want to be doing a string comparison instead of a date comparison so you'll need to use an explicit string comparison function instead of letting ColdFusion infer your intentions. The Compare function will accomplish this task for you.

<cfset academic_year = "2012-13">
<cfoutput>#Compare(academic_year, "2009-10")#</cfoutput>

If for some reason you still wanted to use the GT syntax, you can use Val to convert your two year string into a single year string.

<cfoutput># Val("2012-13") gt Val("2009-10") #</cfoutput>

Is treated as:

<cfoutput># "2012" gt "2009" #</cfoutput>

See Val documentation for how that works.

It's clear that the second one was just casting both sides to dates (incorrectly, but still... CF is "helpful" like that), so the answer is "correct".

I was more interested in why your first expression resulted in a "NO", because it can't be doing a date compare because the LHS is not construable as a date. So it should be doing a string compare, and "2012-13" is greater than "2009-10", so the answer should be "YES" not "NO".

So I dug. Check this code out:

<!--- literal.cfm --->
<cfset var1 = "2012-13">
<cfoutput>#var1 GT "2009-10"#</cfoutput><!--- this outputs: NO --->


<!--- variable.cfm --->
<cfset var1 = "2012-13">
<cfset var2 = "2009-10">
<cfoutput>#var1 GT var2#</cfoutput><!--- this outputs: YES--->

Note they're both comparing "2012-13" to "2009-10".

Why does it do this? Because... if I am reading the decompiled code correctly... CF treats the literal "2009-10" in the first expression as a date (Oct 1, 2009)... then sees that it needs to be compared to a string ("2012-13" cannot be cast to a date), and seems to convert the date "Oct 1, 2009" back into a string ("40087"... the number of days between Dec 31, 1899 and Oct 1, 2009). And "2012-13" is "less than" "40087" when doing a string compare.

Nowhere in the decompiled code for literal.cfm does "2009-10" exist. The only reference is "40087.0D". So CF looked at "2009-10", despite clearly being a string (quotes around it, etc), and said "yeah, that's a date", even though it's hard-coded into an expression where it cannot be used as a date. Sigh.

So, anyway, that's why you're seeing what you're seeing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM