Ask Ben: Formatting A Date Span In ColdFusion
I'm new to CF. I have values for startDate and endDate. Let's say my startDate is June 12, 2009 and my endDate is June 30, 2009. How do I display it to look like 'June 12-30, 2009'. And if the months are different for startDate and endDate, how do I display 'June 12 - December 12, 2009'. Thank you for your help.
In ColdFusion, there's no inherent way to format a date span. However, using ColdFusion's DateFormat() method, we can easily come up with some logic to format the span between two dates. Looking at your question, I see three different date span formatting scenarios:
Two dates in different years.
Two dates in the same year, but different months.
Two dates in the same year and the same month.
Each of these three scenarios will require a different format. If we start to think in terms of date masks (which are used by ColdFusion's DateFormat() method), we can see the above three scenarios as using these three date masks:
mmmm d, yyyy - mmmm d, yyyy
mmmm d - mmmm d, yyyy
mmmm d-d, yyyy
Now, of course we can't use DateFormat() to format two dates at the same time - that's where our logic comes into play. And, since this is something that might be called multiple times (at least three to test with), I am going to wrap the logic up into a ColdFusion user defined function (UDF) such that we don't have to repeat our logic every time we want to perform this action:
<cffunction
name="DateSpanFormat"
access="public"
returntype="string"
output="false"
hint="I take two dates and format their time span.">
<!--- Define arguments. --->
<cfargument
name="From"
type="any"
required="true"
hint="I am the from date/time."
/>
<cfargument
name="To"
type="any"
required="true"
hint="I am the to date/time."
/>
<!--- Define the local scope. --->
<cfset var LOCAL = {} />
<!---
Check to see if the dates are the same year. If they are,
then we can format a compact time span. If they are not
the same year, then we have not special format.
--->
<cfif (Year( ARGUMENTS.From ) EQ Year( ARGUMENTS.To ))>
<!---
Now that we know the dates are the same year, let's
see how compact we can format the span. If they are
the same month, we can go even smaller.
--->
<cfif (Month( ARGUMENTS.From ) EQ Month( ARGUMENTS.To ))>
<!---
Return same-month span.
Example: June 12-30, 2009
--->
<cfreturn (
DateFormat( ARGUMENTS.From, "mmmm d" ) &
"-" &
DateFormat( ARGUMENTS.To, "d, yyyy" )
) />
<cfelse>
<!---
Return same-year span.
Example: June 12 - December 12, 2009
--->
<cfreturn (
DateFormat( ARGUMENTS.From, "mmmm d" ) &
"-" &
DateFormat( ARGUMENTS.To, "mmmm d, yyyy" )
) />
</cfif>
<cfelse>
<!--- Just return a two-part date span format. --->
<cfreturn (
DateFormat( ARGUMENTS.From, "mmmm d, yyyy" ) &
" - " &
DateFormat( ARGUMENTS.To, "mmmm d, yyyy" )
) />
</cfif>
</cffunction>
As you can see, the UDF takes the two dates for which we want to format the time span. It then checks to see which of the above three date span scenarios the two dates fall into and returns the appropriate date span string. While ColdFusion's DateFormat() method cannot format two dates at the same time, you can see in the above UDF that we are using DateFormat() to return partial date formats which we then concatenate to form a full date span value.
To test this, I tried inputting date spans for each of the three scenarios above:
<!--- Output some testing. --->
<cfoutput>
<!--- Different years. --->
#DateSpanFormat( "12/10/2008", "2/15/2009" )#<br />
<br />
<!--- Same year, different months. --->
#DateSpanFormat( "1/10/2009", "2/15/2009" )#<br />
<br />
<!--- Same year, same month. --->
#DateSpanFormat( "2/10/2009", "2/15/2009" )#<br />
</cfoutput>
When I run the above code, I get the following output:
December 10, 2008 - February 15, 2009
January 10-February 15, 2009
February 10-15, 2009
ColdFusion makes working with dates and times extremely easy, but sometimes we have to build a little logic around what it gives us. I hope that helps.
Want to use code from this post? Check out the license.
Reader Comments
Pretty nice. Do you get to post some of these your UDFs to cflib.org?
@William,
I keep meaning to, but am always struggling to find the time.
I have been using the DateRangeFormat UDF from 2004:
http://www.cflib.org/udf/DateRangeFormat
@James,
Looks good. Looks to do just about the same thing with a few more options.
or you know, use icu4j's dateIntervalFormat class:
http://icu-project.org/apiref/icu4j/com/ibm/icu/text/DateIntervalFormat.html
@PaulH,
Ha ha :) I like it - but in the interest of the new programmer who asked, I feel like we should try to avoid Java integration.
too many cool java libs to ignore, might as well try to stop a freight train by winking at it.
Very nice. We use ICU4J but if you look at the implementation examples, it's much more complex.
So, if you know you won't need the i18n aspect then this is a neat solution.
@ciaran that's pretty funny, "if" i looked at the implementation examples.
actually it's no more than what ben's done with his function but w/out all the brain sweat (it's really only 3-4 lines of code). while ben's only written a few lines of code, i imagine quite a bit of thought went into this. and of course, there's a richness in icu4j that's hard to match. but you already know that.
Actually, when I said 'you' I meant it in the plural sense :)
There are times when you cannot beat icu4j - that goes without saying.
Hey Ben,
Thanks for answering my Date Formatting question. As a CF beginner, I was afraid you were going to give me a complicated answer that I won't be able to follow (no java), but I actually understood it. It was logical and simple.
@Helena,
Glad that I could help out! I try to explain things as thoroughly as possible. If you get stumped again, drop me a line.
Nice technique.
Hi Ben,
I have a date_entry column in my database...
I need to enetr the current date in dddd/yy/mm
format.
I have used the dateformat while inserting into the database ,requirement is such a way like i am getting the date value from another query and inserting the same to database in my query...But the problem is I am unable to remove the 'ts'..I mean even 'ts' is also getting inserted into the table along withe date as shown here...{'ts' 20009/10/09} ...I just need to insert 20009/10/09...
Please advise Ben...
Thanks
@Abhijit,
I am a bit confused by your notation. Why do you need four days (dddd)? And, in the database what does "20009" stand for in terms of days?
As far as the "ts" is concerned, if you really want to remove that, you might have to change the data type of the column to be a varchar value. I am not exactly sure why you would want to remove the TS - you can simply format the date when you pull it out of the database.