Skip to main content
Ben Nadel at cf.Objective() 2010 (Minneapolis, MN) with: Justin Mclean
Ben Nadel at cf.Objective() 2010 (Minneapolis, MN) with: Justin Mclean ( @JustinMclean )

Adding CreateTimeSpan() To Date/Time Values In ColdFusion

By on
Tags:

In ColdFusion, it's trivial to add a given date-part, such an "hour" or a "day", to an existing date - there are built-in functions and member-methods for this task. But, it's a little harder to mix "Dates" with "Time Spans". Doing so, often leads to a fractional numeric value. This fractional value is a "numeric date". There are a number of ways to cast between "numeric dates" and "dates"; but, I wanted to look at how we can avoid casting by thinking about what a "time span" actually is; and, how we can efficiently add and remove time spans to and from dates in ColdFusion.

To lay the foundation for this approach, it's important to understand that, in ColdFusion, there are two types of dates: standard dates and numeric dates. Ultimately, both of these types are represented by a numeric value; but, the numeric values are different. The standard date is represented (under the hood) as the number of milliseconds since Epoch Time (aka, Unix Time). The numeric date, on the other hand, is represented as the number of fractional days since ColdFusion Epoch Time.

The "fractional days since ColdFusion epoch time" is a time span. And it is the same type of value that is produced by the createTimeSpan() built-in function. These fractional, numeric dates / time spans have second-level precision. Which means, we can convert a fractional time span to a number of seconds by multiplying the value by the number of seconds in a 24-hour period.

Once we understand that a numeric date / time span can be represented as a number of seconds, adding it to a standard date becomes nothing more than a matter of adding a given value to the "seconds" ('s') date-part of a standard date.

To see this in action, let's try adding createTimeSpan(1,1,1,1) to the current date. What we expect is that the days, hours, minutes, and seconds should all be incremented by 1:

<cfscript>

	// A "Time Span" represents a fraction of "numeric days". In ColdFusion, a date can be
	// represented as a numeric value which is the number of factional days since the
	// "ColdFusion Epoch" (which is not to be confused with the "Unix Epoch").
	timeSpan = createTimeSpan( 1, 1, 1, 1 ); // => 1.04237268519

	// ColdFusion's numeric dates only have SECOND-level precision. Which means, we can
	// model the numeric days as the number of seconds in a 24-hour period.
	secondsInDay = 86400; // => ( 60 * 60 * 24 )

	// We can then easily adjust a given date by adding / subtracting the number of
	// seconds represented by the given time span.
	secondsInTimeSpan = fix( timeSpan * secondsInDay );

	// Add the timespan to the current date - all date parts should be incremented by 1.
	currentDate = now();
	futureDate = currentDate.add( "s", secondsInTimeSpan );

	echoLine( "Time Span:", timeSpan );
	echoLine( "Cur. Date:", currentDate );
	echoLine( "Fut. Date:", futureDate );

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	/**
	* I output all the simple arguments on to a line, followed by a line-break.
	*/
	public void function echoLine( required any value ) {

		writeOutput( arrayToList( arguments, " " ) & "<br />" );

	}

</cfscript>

As you can see, we're converting the time span (factional numeric days) to seconds by multiplying it by the number of seconds in a 24-hour period, 86400. We then add that number of seconds to the current date. And, when we run this ColdFusion code, we get the following output:

Time Span: 1.04237268519
Cur. Date: {ts '2022-04-05 11:27:02'}
Fut. Date: {ts '2022-04-06 12:28:03'}

Two things to note here: first, the value that we are left with is a standard date/time stamp - not a numeric date. And second, we received the expected result: the days, hours, minutes, and seconds were all incremented by 1.

While there's a number of lines of code in the above example, this can easily be collapsed down to a one-liner. Let's look at the same demo, this time using a user-defined function (UDF) - dateAddTimeSpan() - that encapsulates the logic:

<cfscript>

	// This time, let's use our User Defined Function (UDF) to do the same thing. This
	// just hides the complexity of the numeric dates.
	currentDate = now();
	futureDate = dateAddTimeSpan( currentDate, createTimeSpan( 1, 1, 1, 1 ) );
	pastDate = dateAddTimeSpan( currentDate, - createTimeSpan( 1, 1, 1, 1 ) );

	echoLine( "Cur. Date:", currentDate );
	echoLine( "Fut. Date:", futureDate );
	echoLine( "--" );
	echoLine( "Cur. Date:", currentDate );
	echoLine( "Pas. Date:", pastDate );

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	/**
	* I add the given timespan (fractional number of numeric days) to the given date.
	*/
	public date function dateAddTimeSpan(
		required date input,
		required numeric timeSpan
		) {

		// NOTE: I'm using the built-in functions, not the member methods, so that the
		// input date can be more flexible (such as being a numeric date).
		return( dateAdd( "s", fix( 86400 * timeSpan ), input ) );

	}


	/**
	* I output all the simple arguments on to a line, followed by a line-break.
	*/
	public void function echoLine( required any value ) {

		writeOutput( arrayToList( arguments, " " ) & "<br />" );

	}

</cfscript>

This time, not only are we demonstrating the 1-line-of-code that is required to add a createTimeSpan() value to a date/time in ColdFusion, we're also demonstrate that it works equally well with both positive and negative time spans. And, when we run this ColdFusion code, we get the following output:

Cur. Date: {ts '2022-04-05 11:37:06'}
Fut. Date: {ts '2022-04-06 12:38:07'}
--
Cur. Date: {ts '2022-04-05 11:37:06'}
Pas. Date: {ts '2022-04-04 10:36:05'}

As you can see, with createTimeSpan( 1, 1, 1, 1 ) we're incrementing each date-part by 1 in the first test and then decrementing each date-part by 1 in the second test. Easy peasy!

I've been fascinated with "Date Math" in ColdFusion since the very inception of this blog. And, having a good mental model for the various "modes" of date in ColdFusion has proven to be super helpful within data manipulation algorithms. Hopefully, this post has shed some insight onto how you can start to mix-and-match standard dates with time spans in your ColdFusion code.

Want to use code from this post? Check out the license.

Reader Comments

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel