Ask Ben: Displaying And Formatting The Difference Between Two Dates
Posted August 13, 2008 at 9:04 AM
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
Newer Post
OOPhoto - No More Validation In The Controller
Older Post
OOPhoto - More Thoughts On Data Validation In Object Oriented ColdFusion Programming
Reader 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
@Steve,
That's some slick stuff.
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
@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.
Ahh... got it. Thanks mucho.
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.
/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
@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!
@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!
@Grant,
Hmm, funky. I haven't used it a ton; seems like it used to be a bit buggy!



