admin管理员组文章数量:1434921
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:
SCRIPT
todaysDateMin: dateFns.distanceInWordsToNow(new Date(2022, 6, 2, 0, 0, 15), {addSuffix: true})
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})
Share
Improve this question
edited May 16, 2019 at 7:19
Akrion
18.5k1 gold badge36 silver badges57 bronze badges
asked May 13, 2019 at 11:17
TomTom
5,97421 gold badges85 silver badges134 bronze badges
3
|
3 Answers
Reset to default 25The 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);
本文标签:
版权声明:本文标题:javascript - Countdown in date-fns with years, months, days, hours & minutes - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738059876a2056920.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
differenceInYears
,differenceInMonths
,differenceInDays
etc. All you need to do is to build the final string by using them. In the future, they're planning to introduce an additional parameter todistanceInWords
which would allow to specify the output format. – Tomasz Kasperczyk Commented May 15, 2019 at 12:25