Looping over dates in CFML
A question came up on the CFML Slack a couple of days ago where someone was asking about looping over a date range, e.g. from 1st August 2018 to today. He suggested he was going to “do it the old fashioned way using DateDiffs and DateAdds” so he could do it with “regular numbers”. In CFML, however, looping over dates is possible, like this:
<cfscript> startDate = createDate(2018,08,01); loop from=startdate to=now() index="thisDate" { dump(dateformat(thisDate, 'yyyy-mm-dd')); } </cfscript>
The reason this works is because internally the date is represented as a “regular number” anyway, or the Numeric Date to give it its proper name. It is a number whose integer part represents the number of days since the CFML Server’s Epoch, which by default is December 30, 1899, and whose fractional part represents the time value expressed in hours then divided by 24.
So for the above example, the 1st August 2018, without time, is represented by the number 43313. As the loop
function defaults to increment the number by 1 on each iteration and each 1 in the number represents a day, you can loop day-by-day from one date to another.
There are two functions in CFML specifically for dealing with Numeric Date, these are, getNumericDate( datetime )
and isNumericDate( number )
:
- https://docs.lucee.org/reference/functions/getnumericdate.html
- https://docs.lucee.org/reference/functions/isnumericdate.html
The other date/time functions will accept a Numeric Date as an input, as in the above and below examples using the dateFormat
function to output the date in a specific format.
If therefore, you wanted to do something only on a particular day each month you could use the day
function to check the day of the month, for example, to output the date only of the 1st of each month:
<cfscript> startDate = createDate(2018,08,01); loop from=startdate to=now() index="thisDate" { if (day(thisDate) == 1) { dump(dateformat(thisDate, 'yyyy-mm-dd')); } } </cfscript>
You can try this for yourself on TryCF using this gist:
https://trycf.com/gist/e5c20458bbf2b9f45bf0a5111fb0dbff/lucee5?theme=monokai
So next time you need to do something from one date to another, remember that looping over dates in CFML is possible.
Update
So, after posting this and tweeting about it Brad Wood replied and said it “would be super sweet to be able to control the time unit to loop by week, or hour, etc” and I suggested that it could possibly be achieved with the step
attribute, e.g. step=7
for week.
He did some testing and found that you could use the createTimeSpan
function with the step
attribute to achieve any step you would like, for example:
So, in Brad’s example above it would step in 1-hour intervals from 3pm to 5pm. As Brad said, super sweet!