Ask Ben: Displaying And Formatting The Difference Between Two Dates

Posted August 13, 2008 at 9:04 AM

Tags: ColdFusion, Ask Ben

Sir, i want to know the solution for which iam struggling for some days... that is how we have to caluculate difference between two dates such that it have to show the difference in the format yyyy (years):m (months): ww (weaks):w (weakdays) : h (hours): n (minutes) : s (seconds). Sir, to confirm exactly what my doubt mean is...if we go for ebay ..and if we find there the products displaying and the estimated time left to buy... there they show the time left...like that i want if i gve two dates it have to show the exact difference between them......as shown in above format..

thanking you sir.....for providing the oppurtunity and iam waiting for your reply kindly.......

This task is actually much less complicated than it might sound. ColdFusion is quite excellent at both handling and formatting dates. To solve this problem, at least mostly, all we need to is the following:

  • Find the difference between your two dates (the current time and the target time).
  • Format that difference in the desired way.

As you may have read before, ColdFusion's date math makes finding the difference between two dates simple - all we need to do is treat the dates as numbers and do some subtraction:

 Launch code in new window » Download code as text file »

  • <!--- Get a start date for our comparison. --->
  • <cfset dtFrom = ParseDateTime( "01/01/2008 12:00:00 AM" ) />
  •  
  • <!--- Get the current date. --->
  • <cfset dtTo = Now() />
  •  
  • <!---
  • Get the difference between these two dates. Using
  • ColdFusion Date Math will give us the numeric version
  • of the timespan that represents the difference between
  • these two dates... this timespan is represented in the
  • number of days between the two dates.
  • --->
  • <cfset dtDiff = (dtTo - dtFrom) />
  •  
  •  
  • <!---
  • Now that we have the difference between the two dates, we
  • simply need to format that date/time span using ColdFusion's
  • built-in formatting functions.
  • --->
  • #DateDiff( "yyyy", "12/30/1899", dtDiff )# Years,
  • #DateFormat( dtDiff, "m" )# Months,
  • #DateFormat( dtDiff, "d" )# Days,
  • #TimeFormat( dtDiff, "h" )# Hours,
  • #TimeFormat( dtDiff, "m" )# Minutes,
  • #TimeFormat( dtDiff, "s" )# Seconds

When outputting the difference, you have to be careful of the year. That is one tricky thing in ColdFusion. Dates don't start at zero - they start at 12/30/1899. Therefore, when we get our time span, we have to get the difference in years between our time span value and the "start" date of ColdFusion dates. The rest of the formatting should be straightforward.

Running the above code, we get the following output:

0 Years, 8 Months, 12 Days, 9 Hours, 2 Minutes, 42 Seconds

I hope this puts you on the right track.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page





Reader Comments

Aug 15, 2008 at 3:01 PM // reply »
55 Comments

Ben,

I couldn't resist taking this a little further http://www.stephenwithington.com/blog/index.cfm/2008/8/15/Using-ColdFusion-to-Create-an-Ebayesque-Auction-Countdown-Timer-Custom-Tag


Aug 15, 2008 at 3:06 PM // reply »
7,572 Comments

@Steve,

That's some slick stuff.


Jun 26, 2009 at 2:20 PM // reply »
2 Comments

When I use this functionality for "d", "h" and "m" on a date from an MSSQL database (should it matter?)

<cfset dtFrom = sel_last_call.eventdate/>
<cfset dtTo = Now() />
<cfset dtDiff = (dtTo - dtFrom) />
#DateFormat( dtDiff, "d" )# Day<cfif DateFormat( dtDiff, "d" ) neq 1>s</cfif>,
#TimeFormat( dtDiff, "h" )# Hour<cfif TimeFormat( dtDiff, "h" ) neq 1>s</cfif>,
#TimeFormat( dtDiff, "m" )# Minute<cfif TimeFormat( dtDiff, "m" ) neq 1>s</cfif>

I get some odd results

The difference between
6/23/2009 4:40:00 PM and Now (6/26/09 2:15 pm)
1 Day 9 Hours 35 Minutes

6/24/2009 12:00:00 PM and Now (6/26/09 2:15 pm)
1 Day 2 Hours 15 Minutes


Jun 26, 2009 at 5:37 PM // reply »
7,572 Comments

@Charles,

First off, where the date comes from (MS SQL, MySQL, ACCESS, etc.) is not relevant. The issue you are having is not apparent right away - definitely not intuitive unless you work with date math a lot.

See, when you subtract one date from another using mathematical operators, you create a numeric date value. In the first example you gave, FROM - TO, results in:

2.89930555555

This value is a numeric representation of the time span between your two dates.

Now, the way we numeric dates work is that they are considered the number of days since the ZERO date in ColdFusion, which you can see if you do this:

#DateFormat( 0, "full" )#

... which gives us:

Saturday, December 30, 1899

And so, your mathematical date value, 2.8993...., is consider to be 2.8993.... days AFTER 12-30-1899.

So then, the next thing you are asking it is to get the date of that date:

DateFormat( dtDiff, "d" )

This is giving you "1". This is because if you add 2.899 days to 12-30-1899, you get 1-1-1900. And, the "day" of that is "1".

What you want is NOT the DateFormat() of the time span, but rather the DAYS of the time span, which is:

#Fix( dtDiff )#

Fix() in ColdFusion truncates a number (removes decimal), leaving you with just the integer, which is the number of dates in the time span.

The next issue is that we are dealing with 24 hours, but you are using the small "h", which is 12 hours. So, it gives you 9 hours, but really, its thinking 24 hours time, so its 21.

All together, you need to do this:

<cfset dtFrom = ParseDateTime( "6/23/2009 4:40:00 PM" ) />
<cfset dtTo = ParseDateTime( "6/26/2009 2:15:00 PM" ) />
<cfset dtDiff = (dtTo - dtFrom) />

#Fix( dtDiff )# day(s)
#TimeFormat( dtDiff, "H" )# hour(s)
#TimeFormat( dtDiff, "m" )# miunutes(s)

... which results in :

2 day(s) 21 hour(s) 35 miunutes(s)

I hope that helps clear it up a bit.


Jun 29, 2009 at 7:51 AM // reply »
2 Comments

Ahh... got it. Thanks mucho.


Feb 10, 2010 at 3:13 PM // reply »
8 Comments

Ug....

Ben, thanks man for this post. Date math messes with my head. I was even struggling after I read this because I was skipping steps. I actually had to write out each operation I was doing so I could figure out where I went wrong.

[Now, in my defense I programmed for a solid 14 hours yesterday, but nonethless..]

I wanted to log the ignore the user session for a period of time if they tried too many times to login.

Here's the code that did made the word problem:
<cfset dtFrom = ParseDateTime(session.ignored) />
<cfset dtTo = ParseDateTime(now()) />
<cfset dtDiff = (dtTo - dtFrom) />
<cfset daysAgo = Fix(dtDiff) />
<cfset hoursAgo = TimeFormat( dtDiff, "H" ) />
<cfset minutesAgo = TimeFormat( dtDiff, "H" ) />
<cfset secondsAgo = TimeFormat( dtDiff, "H" ) />
<cfset totalSecondsAgo = (daysAgo * 86400) + (hoursAgo * 3600) + (minutesAgo * 60) + secondsAgo />
<cfset sessionIgnoreSeconds = APPLICATION.ignoreLoginMinutes * 60 />
<cfset ignoreSecondsRemaining = sessionIgnoreSeconds - totalSecondsAgo />
<cfoutput>
Thanks to Ben, i know the session was ignored
#daysAgo# day(s)
#hoursAgo# hour(s)
#minutesAgo# minute(s)
#secondsAgo# second(s) ago.<br />
The application requires an ignore period of #APPLICATION.ignoreLoginMinutes# minute(s)<br />
#APPLICATION.ignoreLoginMinutes# minute(s) is #sessionIgnoreSeconds# seconds(s)<br />
The ignore period has lasted #totalSecondsAgo# second(s)<br />
#sessionIgnoreSeconds# second(s) minus #totalSecondsAgo# second(s)
is #ignoreSecondsRemaining# second(s).<br />
If #ignoreSecondsRemaining# is less than or equal to 0 second(s), the ignore period has expired.<br />
</cfoutput>

Here's the output of the code that I wrote, showing my work [images of math class dance in my head]:

Thanks to Ben, i know the session was ignored 0 day(s) 1 hour(s) 1 minute(s) 1 second(s) ago.
The application requires an ignore period of 2 minute(s)
2 minute(s) is 120 seconds(s)
The ignore period has lasted 3661 second(s)
120 second(s) minus 3661 second(s) is -3541 second(s).
If -3541 is less than or equal to 0 second(s), the ignore period has expired.

Thanks Ben. Date math is the bane of my existence.


Feb 10, 2010 at 5:09 PM // reply »
8 Comments

/me smacks forehead

got it wonky a bit in the code above... code should be:
<cfset dtFrom = ParseDateTime(session.ignored) />
<cfset dtTo = ParseDateTime(now()) />
<cfset dtDiff = (dtTo - dtFrom) />
<cfset daysAgo = Fix(dtDiff) />
<cfset hoursAgo = TimeFormat( dtDiff, "H" ) />
<cfset minutesAgo = TimeFormat( dtDiff, "m" ) />
<cfset secondsAgo = TimeFormat( dtDiff, "s" ) />
<cfset totalSecondsAgo = (daysAgo * 86400) + (hoursAgo * 3600) + (minutesAgo * 60) + secondsAgo />
<cfset sessionIgnoreSeconds = APPLICATION.ignoreLoginMinutes * 60 />
<cfset ignoreSecondsRemaining = sessionIgnoreSeconds - totalSecondsAgo />
<cfoutput>
Thanks to Ben, i know the session was ignored
#daysAgo# day(s)
#hoursAgo# hour(s)
#minutesAgo# minute(s)
#secondsAgo# second(s) ago.<br />
The application requires an ignore period of #APPLICATION.ignoreLoginMinutes# minute(s)<br />
#APPLICATION.ignoreLoginMinutes# minute(s) is #sessionIgnoreSeconds# seconds(s)<br />
The ignore period has lasted #totalSecondsAgo# second(s)<br />
#sessionIgnoreSeconds# second(s) minus #totalSecondsAgo# second(s)
is #ignoreSecondsRemaining# second(s).<br />
If #ignoreSecondsRemaining# is less than or equal to 0 second(s), the ignore period has expired.<br />
</cfoutput>

/me hates date math


Feb 10, 2010 at 10:25 PM // reply »
7,572 Comments

@Grant,

Date math is extremely powerful and can be very frustrating :) Looks like you are getting the hang of it. If I can give you two points of feedback: the now() method already returns a date/time object, so there is no need to parse it. Also, one function that might make your life a little easier is the dateDiff() method. I'm not saying you need it here, but sometimes it is easier than wrappin your head around the date math.

Good stuff!


Feb 11, 2010 at 8:10 AM // reply »
8 Comments

@Ben Nadel,

Thanks. DateDiff() is one of those functions that I'm aware of, but how it really works is a bit foggy to me. I've used it before, but I don't use it much. This could be because it confuses me, or because I haven't needed it. I just checked adobe's documentation and they note something interesting in the change history for CF8:

- Changed how negative date differences are calculated: this function calculates negative date differences correctly; its output may be different from that in earlier releases.

- Changed the w and ww masks; they determine the number of full weeks between the two dates.

Since I'm stuck in CF7 [company has old software], this must be why I don't use DateDiff(). :)

Cheers!


Feb 11, 2010 at 10:16 PM // reply »
7,572 Comments

@Grant,

Hmm, funky. I haven't used it a ton; seems like it used to be a bit buggy!


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 21, 2010 at 3:13 PM
Ask Ben: Javascript String Replace Method
I am trying to make a java program to count the number of times that these punctuation marks occur in a body of text: , : ; . ! - ' " ? / \ I am using this piece to ferret out the commas: numcommas ... read »
Mar 21, 2010 at 11:13 AM
A New Wrist Pain
@chiropractor suwanee, Spoken like someone trying to sell something. Other than for minor, temporary relief from some back pain, chiropractic treatment is nothing but placebo effect and quackery. ... read »
Mar 21, 2010 at 6:32 AM
ColdFusion CFPOP - My First Look
Apologies... The field name in the db for C. is "BounceCode" It stores the code / message which is returned in the email. Sorry for the confusion. ... read »
Mar 21, 2010 at 6:29 AM
ColdFusion CFPOP - My First Look
@Jose Galdamez, Hi Ben and Jose 1st of all.. big thanks to Jose for his Skype chat a few weeks back. Your time was much appreciated. I have come up with a rather unelegant solution to my problem a ... read »
Mar 21, 2010 at 3:42 AM
A New Wrist Pain
Chiropractic treatment is one of the best methods for treating numerous health problems naturally. After years of experience being a chiropractor, I have found that it is a powerful way to solve many ... read »
Mar 20, 2010 at 12:07 PM
Drawing On The iPhone Canvas With jQuery And ColdFusion
Simply awesome. Saved my day. ... read »
Mar 20, 2010 at 9:00 AM
Building A Fixed-Position Bottom Menu Bar (ala FaceBook)
I would like to say thx for an easy way to create a bottom bar. I do have a ?. Is it possible to center the bar if i want to resize it to ex 85%. Regards Offenbach ... read »
Mar 19, 2010 at 7:26 PM
MySQL 3/4 - com.mysql.jdbc.Driver And allowMultiQueries=true
Thank you very much for this post. Adding allowMultiQueries="true" in context.xml didn't help until I added it to url as allowMultiQueries=true Good idea is to use prepared statements and it will he ... read »