Moment is a great library, well crafted, battle tested and supported by a really skilled team, but sometimes folks imports it for convenience, to apply only trivial transformations. Considering its size it might be worth exploring other solutions, when what you are looking for could be achieved with lighter solutions.
This page is a mere exercise to see how can achieve similar functionalities in plain js: it's important to understand how native code compare to libraries and be able to make informed decision on whether to use one. Not all the formatting moment.js offers can be easily achieved with plainJs, but some is.
The project is far from complete. Please contribute on github.
const moment = require('moment')
const second = 1000
const minute = second * 60
const hour = minute * 60
const day = hour * 24
let date = new Date(Date.now() - 20 * second)
moment(date).fromNow()
// a few seconds ago
date = new Date(Date.now() - 60 * second)
moment(date).fromNow()
// a minute ago
date = new Date(Date.now() - 2 * minute)
moment(date).fromNow()
// 2 minutes ago
date = new Date(Date.now() - 45 * minute)
moment(date).fromNow()
// an hour ago
date = new Date(Date.now() - 3 * hour)
moment(date).fromNow()
// 3 hours ago
date = new Date(Date.now() - 1 * day)
moment(date).fromNow()
// a day ago
date = new Date(Date.now() - 5 * day)
moment(date).fromNow()
// 5 days ago
date = new Date(Date.now() - 44 * day)
moment(date).fromNow()
// a month ago
date = new Date(Date.now() - 120 * day)
moment(date).fromNow()
// 4 months ago
date = new Date(Date.now() - 365 * day)
moment(date).fromNow()
// a year ago
date = new Date(Date.now() - 2500 * day)
moment(date).fromNow()
// 7 years ago
const timeAgo = (() => {
const second = 1000
const minute = second * 60
const hour = minute * 60
const day = hour * 24
const thresholds = [
{ threshold: 540 * day, modifier: 365 * day, render: elapsed => `${elapsed} years ago` },
{ threshold: 320 * day, render: () => 'a year ago' },
{ threshold: 45 * day, modifier: 30 * day, render: elapsed => `${elapsed} months ago` },
{ threshold: 26 * day, render: () => 'a month ago' },
{ threshold: 36 * hour, modifier: 24 * hour, render: elapsed => `${elapsed} days ago` },
{ threshold: 22 * hour, render: () => 'a day ago' },
{ threshold: 90 * minute, modifier: 60 * minute, render: elapsed => `${elapsed} hours ago` },
{ threshold: 45 * minute, render: () => 'an hour ago' },
{ threshold: 90 * second, modifier: 60 * second, render: elapsed => `${elapsed} minutes ago` },
{ threshold: 46 * second, render: () => 'a minute ago' },
{ threshold: 0 * second, render: () => 'a few seconds ago' },
]
return date => {
const elapsed = Math.round(new Date() - date)
const { render, modifier } = thresholds.find(({ threshold }) => elapsed >= threshold)
return render(Math.round(elapsed / modifier))
}
})()
// duplicating just for testing purposes
const second = 1000
const minute = second * 60
const hour = minute * 60
const day = hour * 24
let date = new Date(Date.now() - 20 * second)
timeAgo(date)
// a few seconds ago
date = new Date(Date.now() - 60 * second)
timeAgo(date)
// a minute ago
date = new Date(Date.now() - 2 * minute)
timeAgo(date)
// 2 minutes ago
date = new Date(Date.now() - 45 * minute)
timeAgo(date)
// an hour ago
date = new Date(Date.now() - 3 * hour)
timeAgo(date)
// 3 hours ago
date = new Date(Date.now() - 1 * day)
timeAgo(date)
// a day ago
date = new Date(Date.now() - 5 * day)
timeAgo(date)
// 5 days ago
date = new Date(Date.now() - 44 * day)
timeAgo(date)
// a month ago
date = new Date(Date.now() - 120 * day)
timeAgo(date)
// 4 months ago
date = new Date(Date.now() - 365 * day)
timeAgo(date)
// a year ago
date = new Date(Date.now() - 2500 * day)
timeAgo(date)
// 7 years ago