I am prepend
ing a html document, so when user post a comment, it shows up in real time. Now the problem is the way the date is looking, i want the date to show in a format like this 3s ago
and not 09/08/2022 2:41 p.m.
, what is the best to achieve this
let _html = '
<div >
<h4><b>{{c.user.username|title}}</b> <span>{% now "SHORT_DATETIME_FORMAT" %} ago</span></h4>
<p>' _comment '</p>
</div>\
' $(".comment-wrapper").prepend(_html)
CodePudding user response:
Here's a working proof of concept, without using any external libraries. It basically just converts seconds to minutes if it's over 60, minutes to hours if over 60, hours to days if over 24, etc...
/* Given two timestamp, return the difference in text format, e.g. '10 minutes' */
const getTimeDifference = (startTime, endTime) => {
const msDifference = new Date(endTime).getTime() - new Date(startTime).getTime();
const diff = Math.abs(Math.round(msDifference / 1000));
const divide = (time, round) => Math.round(time / round);
if (diff < 60) return `${divide(diff, 1)} seconds`;
if (diff < 3600) return `${divide(diff, 60)} minutes`;
if (diff < 86400) return `${divide(diff, 3600)} hours`;
if (diff < 604800) return `${divide(diff, 86400)} days`;
if (diff < 31557600) return `${divide(diff, 604800)} weeks`;
if (diff >= 31557600) return `${divide(diff, 31557600)} years`;
return 'unknown';
};
/* Given a timestamp, return how long ago it was, e.g. '10 minutes' */
const getTimeAgo = (dateTime) => {
const now = new Date().getTime();
const isHistorical = new Date(dateTime).getTime() < now;
const diffStr = getTimeDifference(dateTime, now);
if (diffStr === 'unknown') return diffStr;
return isHistorical ? `${diffStr} ago` : `in ${diffStr}`;
};
/* Update the UI at intervals */
const startTime = new Date();
const timer = setInterval(() => {
document.getElementById('comment').innerHTML = getTimeAgo(startTime);
}, 1000);
<p id="comment"></p>
CodePudding user response:
const dateFormater = function(date: Date) {
// if the date is not a date object, return error
if (Object.prototype.toString.call(date) !== "[object Date]") {
return "Invalid Date";
}
let normalizedDate = new Date(date);
let now = new Date();
let format = (num, type) => {
if (type === 'Hour' && num === 1) return 'An hour ago';
else if (num > 1) return `${num} ${type}s ago`;
else return `${num} ${type} ago`;
}
// if the seconds difference is less than 60, return "Just now"
if (Math.floor((now.getTime() - normalizedDate.getTime()) / 1000) < 60) {
// no need to call the format `function` here
return 'Just now';
}
// if the seconds difference is less than 3600, return "X minutes ago"
else if (Math.floor((now.getTime() - normalizedDate.getTime()) / 1000) < 3600) {
return format(Math.floor((now.getTime() - normalizedDate.getTime()) / 1000 / 60), 'Minute');
}
// if the seconds difference is less than 86400, return "X hours ago"
else if (Math.floor((now.getTime() - normalizedDate.getTime()) / 1000) < 86400) {
return format(Math.floor((now.getTime() - normalizedDate.getTime()) / 1000 / 60 / 60), 'Hour');
}
// if the seconds difference is less than 604800, return "X days ago"
else if (Math.floor((now.getTime() - normalizedDate.getTime()) / 1000) < 604800) {
return format(Math.floor((now.getTime() - normalizedDate.getTime()) / 1000 / 60 / 60 / 24), 'Day');
}
// else return the normalizedDate in the format "DD/MM/YYYY"
else {
return normalizedDate.toLocaleDateString();
}
};
//usage
let dateToFormat = new Date()
let formatterInterval = setInterval(()=> {
console.log(dateFormater(dateToFormat))
},6000) // or however seconds you like
You can now setInterval to say 1000ms to be updating the dates in them almost realistically.
If you have a very large data/comments, you may also want to kind of create a register for those that have already passed the parsing threshold e.g those comments that are more than one week old so that they don't have to pass through this function agian (if you are a minimalist like me though)