I by-and-large agree 100% with Brad, bar one point. In CFML a date def is type of object, and this is important:
writeDump([
now().getClass().getName(),
createDate(2011,3,24).getClass().getName(),
createDateTime(2011,3,24,9,2,0).getClass().getName(),
lsParseDateTime("2011-03-24").getClass().getName()
])
(all lucee.runtime.type.dt.DateTimeImpl
on Lucee; coldfusion.runtime.OleDateTime
on CF).
The reason why strings work in some situations is simply down to CFML’s loose & dynamic typefulness. If you give a function that’s expecting a date something that can be converted to a date: it’ll be converted to a date. This works for some strings depending on their format, eg:
function f(date d) {
return dateAdd("d", 1, d)
}
writeDump(f("3/5/2023").format("mmmm d")) // March 6
Obviously because I’m not a lunatic, the answer there ought to be May 4, but CFML can only guess at ambiguously-formatted strings. And thanks to our USAn friends, a/b/cccc
is an ambiguous string format, for values of b
1-12. Thanks guys.
So anyway, that’s one example of why it’s always best to use actual dates when working with dates.
Equally, when a function expects a string or a number, then CFML will do its best to treat a date object appropriately:
d = now()
f = d + 1
writeOutput(f) // 44997.45065489583
writeOutput(now()) // {ts '2023-03-11 10:49:33'}
And this also explains what Brad said about not being able to call date methods on strings-that-look-like-dates. If dates actually were simply specially-formatted strings in CFML, then one would legitimately expect "2011-03-24".add("d",1)
to work, given "2011-03-24"
would qualify as one of those “specially-formatted-strings-that-are-dates-in-CFML”. But they’re not, so it doesn’t.
Now. According to CFML… isDate("2.3")
. Is it?
This is a another good example of why one should not use strings or numbers when dates are expected. Check this.
writeDump([
isDate("2.3")
dateAdd("d", 0, "2.3") // reminder: datepart, number, date
])
Lucee:
true
{ts ‘2023-02-03 00:00:00’}
So “2.3” is interpreted as “m.d”. I’m not sure that’s a date format anyone uses, but… OK.
But… CF:
No
{ts ‘1900-01-01 07:12:00’}
What’s going on here?
Like me, CF goes “no, ‘2.3’ is not a date, you weirdo”.
But then it seems to contradict itself and goes (I’m guessing) “OK well "2.3"
isn’t a date, but it’s a string representation of 2.3
, and I can interpret that as 2.3 days after my zero date (which is 1899-12-30
. Don’t ask)”.
This isn’t a contradiction, although it’s perhaps not entirely expected, either.
And demonstrates… do not use strings or numbers when you are supposed to be dealing with dates.
Also: those are two bugs in Lucee there.
Bottom line: all CFML devs (and Lucee devs, it seems
) need to be really comfortable with how CFML’s loose/dynamic typing works. It’s fundamental to our jobs.