Reputation: 7573
I couldn't articulate my title very well but what I am trying to do is show the difference between two dates progressively until the highest unit of measurement can be used.
What this means is that I want to show the difference initially by seconds using #DateDiff('s', mydate, Now())#
. After 60 seconds it should show the difference in minutes. After 60 minutes I want it to show the difference by Hours and Minutes together. Then after 24 hours, it should show the difference by Days and Hours. And so on until weeks, months, years are covered.
I can only imagine doing it using a big <cfif>
statement and just wondered if there's a better way to do it before I start writing this thing.
Upvotes: 0
Views: 105
Reputation: 5510
<cfscript>
function CalcAge(Date1,Date2,depth) {
param name="Arguments.depth" default="0";
// Only alter local["partlist"] to list the dateparts you want to calculate.
// Partlist args = cx = century, dx = decade, yyyy = year, m = month, ww = week, d = day, h = hour, n = minute, s = second
// Partlist should also be in descending order.
// Known Issue: The last element of partlist must be a coldfusion-recognized datepart (yyyy,m,ww,d,h,n,s)
local["partlist"] = "cx,yyyy,m,ww,d,h,n,s";
local["partWords"] = {cx="century,centuries",dx="decade,decades",yyyy="year,years",m="month,months",ww="week,weeks",d="day,days",h="hour,hours",n="minute,minutes",s="second,seconds"};
local["fDates"] = {};
// Decide which date is more recent, make the more recent as gDate
if (DateCompare(Arguments["Date1"],Arguments["Date2"]) == -1) {
// The First date is earlier than the second date
local["fDates"]["lDate"] = Arguments["Date1"];
local["fDates"]["gDate"] = Arguments["Date2"];
} else if (DateCompare(Arguments["Date1"],Arguments["Date2"]) == 1) {
// The second date is earlier than the first date, switch them
local["fDates"]["lDate"] = Arguments["Date2"];
local["fDates"]["gDate"] = Arguments["Date1"];
} else {
// The dates are equal, return and exit.
return "0";
}
local["Difference"]=StructNew();
local["pString"] = "";
local["fDates"]["chDate"] = local["fDates"]["gDate"];
local["cDepth"] = 0;
while (DateDiff(listLast(local["partlist"]),local["fDates"]["lDate"],local["fDates"]["chDate"]) > 0) {
for (i = 1; i <= listlen(local["partlist"]); i++) {
ix = listGetAt(local["partlist"],i);
param name="local.Difference.#ix#" default="0";
if (ix == "cx") { // centuries
while (DateDiff("yyyy",local["fDates"]["lDate"],local["fDates"]["chDate"]) >= 100) {
local["fDates"]["chDate"] = DateAdd("yyyy",-100,local["fDates"]["chDate"]);
local["Difference"][ix] += 1;
}
} else if (ix == "dx") { // decades
while (DateDiff("yyyy",local["fDates"]["lDate"],local["fDates"]["chDate"]) > 10) {
local["fDates"]["chDate"] = DateAdd("yyyy",-10,local["fDates"]["chDate"]);
local["Difference"][ix] += 1;
}
} else {
if (DateDiff(ix,local["fDates"]["lDate"],local["fDates"]["chDate"]) > 0) {
local["Changeby"] = DateDiff(ix,local["fDates"]["lDate"],local["fDates"]["chDate"]);
local["fDates"]["chDate"] = DateAdd(ix,0-Abs(local["changeby"]),local["fDates"]["chDate"]);
local["Difference"][ix] = local["changeby"];
}
}
if (local["Difference"][ix] > 0) {
local["cDepth"] = local["cDepth"] + 1;
local["pString"] = listAppend(local["pString"],"#local["Difference"][ix]# #ListGetAt(local["partWords"][ix],min(2,local["Difference"][ix]))#",",");
if (local["cDepth"] == Arguments["depth"]) {
return replace(local["pString"],",",", ","ALL");
}
}
}
}
return replace(local["pString"],",",", ","ALL");
}
</cfscript>
And to use the function:
<cfoutput>Adding 13 months. #CalcAge(Now(),DateAdd("m",13,Now()))#<br><br>
Brief: #CalcAge(Now(),DateAdd("m",13,Now()),2)#<br><br>
Adding 135 years. #CalcAge(DateAdd("yyyy",135,Now()),Now())#<br><br>
Brief: #CalcAge(Now(),DateAdd("yyyy",135,Now()),2)#<br><br>
Adding 73 hours. #CalcAge(Now(),DateAdd("h",73,Now()))#<br><br>
Brief: #CalcAge(Now(),DateAdd("h",73,Now()),2)#<br><br>
Depth: 100 (because none will have 100 elements); #CalcAge(Now(),DateAdd("s",1000000000,Now()),100)#<br><br>
Depth: 4; #CalcAge(Now(),DateAdd("s",1000000000,Now()),4)#<br><br>
Depth: 3; #CalcAge(Now(),DateAdd("s",1000000000,Now()),3)#<br><br>
Depth: 2; #CalcAge(Now(),DateAdd("s",1000000000,Now()),2)#<br><br>
Depth: 1; #CalcAge(Now(),DateAdd("s",1000000000,Now()),1)#<br><br>
Depth: 0 (depth 0 means unlimited); #CalcAge(Now(),DateAdd("s",1000000000,Now()),0)#<br><br></cfoutput>
This should do exactly what you're looking for.
The first two parameters are dates, should be passed as CalcAge(Date1,Date2).
If you set the third parameter, "depth" to a number, it rounds the age down at the largest unit measured (A depth of 2 would say '6 days, 4 hours' rather than '6 days, 4 hours, 3 minutes, 28 seconds').
Upvotes: 1