A friend asked recently how I would go about writing a function to do fuzzy time - something that formats time in a casual way, the way you would talk about it in conversation - “just now”, “a few minutes ago”, “2 days ago”, etc. He wanted it to be customizable, where they could define the groupings used. This is what we came up with:
<cfscript>
/**
* Displays a formatted approximation of how long ago a timestamp was.
*
* @param input - Date to Format (required)
* @param defaultMask - the date mask if the date is earlier than the earliest case. Default dd MMM, YYYY
* @return Returns a string.
* @author Ryan Guill ([email protected] ), Adam Tuttle ([email protected] )
* @version 1, Sept 11, 2014
*
* To customize, add a struct to the map for your case. Order matters, cases are
* evaluated in order, the first one that matches will be used. In the structure,
* n is the amount, p is the datepart (see dateDiff for options), and m is the message.
* You can use {x} for the amount and {s} for an optional pluralization of the
* message if the amount != 1;
*
* ACF 9+
*
* https://gist.github.com/ryanguill/a0b4bd5092b6044824c9
*/
string function fuzzy (required date input, string defaultMask = 'dd MMM, YYYY') {
var now = now();
var map = [
{ n: 60, p: "s", m: "just now" }
, { n: 60, p: "n", m: "{x} min{s} ago" }
, { n: 24, p: "h", m: "{x} hr{s} ago" }
, { n: 2, p: "d", m: "yesterday" }
, { n: 7, p: "d", m: "{x} day{s} ago" }
];
for ( var item in map ) {
var x = dateDiff( item.p, input, now );
if ( x < item.n ) {
return item.m.replace("{x}", x).replace("{s}", x == 1 ? '' : 's');
}
}
return dateFormat( input, defaultMask );
}
inputs = [
dateAdd("s", -1, now())
, dateAdd("s", -30, now())
, dateAdd("n", -1, now())
, dateAdd("n", -30, now())
, dateAdd("d", -1, now())
, dateAdd("d", -15, now())
, dateAdd("m", -1, now())
, dateAdd("m", -2, now())
, dateAdd("m", -11, now())
, dateAdd("m", -15, now())
, dateAdd("yyyy", -1, now())
, dateAdd("yyyy", -5, now())
, dateAdd("yyyy", -50, now())
];
</cfscript>
<cfoutput>
<cfloop array="#inputs#" index="input">
#input#: #fuzzy(input)#<br />
</cfloop>
</cfoutput>