I'm using DateFNS and I need to generate a countdown with it. distanceInWordsToNow
only outputs in about 3 years but I need the exact time like 3 Years, 11 Months, 20 Days, 3 Hours, 2 Minutes
. How to archive that with DateFNS?
Here is a CodePen example: https://codepen.io/anon/pen/qGajJB
SCRIPT
todaysDateMin: dateFns.distanceInWordsToNow(new Date(2022, 6, 2, 0, 0, 15), {addSuffix: true})
date-fns respects timezones & DST. It follows semantic versioning so, always backward compatible. Each build CI checks more than 650 000 examples in about 400 time zones. The best API is an API that doesn't exist.
Date-fns simplifies the JavaScript data manipulations by providing a variety of functions. It provides more than 200 different time-related functions, and unlike MomentJS, it allows you to import a selected set of functions as needed.
//import the function you want to use const {format} = require('date-fns'); const {format} = require('date-fns'); //today's date const today =format(new Date(),'dd. MM. yyyy'); console.
date-fns provides the most comprehensive, yet simple and consistent toolset. for manipulating JavaScript dates in a browser & Node. js.
The formatDuration()
function in date-fns v2 does exactly what you want it to.
import { formatDuration, intervalToDuration } from 'date-fns'
let duration = intervalToDuration({
start: new Date(2022, 6, 2, 0, 0, 15),
end: new Date(),
})
formatDuration(duration, {
delimiter: ', '
})
// 2 years, 15 days, 23 hours, 49 minutes, 35 seconds
You can even filter it.
// take the first three nonzero units
const units = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds']
const nonzero = Object.entries(duration).filter(([_, value]) => value || 0 > 0).map(([unit, _]) => unit)
formatDuration(duration, {
format: units.filter(i => new Set(nonzero).has(i)).slice(0, 3),
delimiter: ', '
})
// 2 years, 15 days, 23 hours
You can try something like this:
let humanizeFutureToNow = fDate => {
let result = [], now = new Date()
let parts = ['year', 'month', 'day', 'hour', 'minute']
parts.forEach((p, i) => {
let uP = p.charAt(0).toUpperCase() + p.slice(1)
let t = dateFns[`differenceIn${uP}s`](fDate, now);
if (t) {
result.push(`${i===parts.length-1 ? 'and ' : ''}${t} ${uP}${t===1 ? '' : 's'}`);
if (i < parts.length)
fDate = dateFns[`sub${uP}s`](fDate, t);
}
})
return result.join(' ');
}
console.log(humanizeFutureToNow(new Date('2022-11-11')))
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js"></script>
The idea is to run through all the time periods you want (and have supported date-fns functions) and generate an array with all the strings. We do this by running the supported differenceIn<PARTGOESHERE>
first to get the time distance
and then subtract it using the sub<PARTGOESHERE>
function. After that just join them to compose the final string.
From here you can customize and export the parts as a parameter, as well as the uppercasing of the first letters in the output etc etc.
Here is also a lodash version:
let humanizeFutureToNow = fDate => {
let result = [], now = new Date()
let parts = ['year', 'month', 'day', 'hour', 'minute']
_.each(parts, (p, i) => {
let scPart = _.startCase(p)
let t = _.invoke(dateFns, `differenceIn${scPart}s`, fDate, now);
if (t) {
result.push(`${i===parts.length-1 ? 'and ' : ''}${t} ${scPart}${t===1 ? '' : 's'}`);
if (i < parts.length)
fDate = _.invoke(dateFns, `sub${scPart}s`, fDate, t);
}
})
return result.join(' ');
}
console.log(humanizeFutureToNow(new Date('2022-11-11')))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js"></script>
Use the following dateFns functions to get the components, then concatenate them together with the strings.
let x be the smaller year, y be the larger save differenceInYears called on x and y which gives the whole number of years in a variable pass x and that as a parameter to addYears, assign to x
call differenceInMonths on x and y, save call addMonths on x and that saved number of months
do the same with differenceInDays and addDays, differenceInHours and addHours Now x is less than 60 minutes away from y, so call differenceInMinutes and you're done (assuming your countDown is down to the minute).
Here is your example as run on runkit.com to illustrate the method.
var dateFns = require("date-fns");
var x = new Date();
var y = new Date(2022, 2, 6, 0, 0, 15);
var temp;
temp = dateFns.differenceInYears(y, x);
var result = temp + " years ";
x = dateFns.addYears(x, temp);
temp = dateFns.differenceInMonths(y, x);
result = result + temp + " months ";
x = dateFns.addMonths(x, temp);
temp = dateFns.differenceInDays(y, x);
result = result + temp + " days ";
x = dateFns.addDays(x, temp);
temp = dateFns.differenceInHours(y, x);
result = result + temp + " hours ";
x = dateFns.addHours(x, temp);
temp = dateFns.differenceInMinutes(y, x);
result = result + temp + " minutes ";
x = dateFns.addMinutes(x, temp);
temp = dateFns.differenceInSeconds(y, x);
result = result + temp + " seconds";
console.log(result);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With