带有年、月、日、小时和分钟的 date-fns 倒计时

Posted

技术标签:

【中文标题】带有年、月、日、小时和分钟的 date-fns 倒计时【英文标题】:Countdown in date-fns with years, months, days, hours & minutes 【发布时间】:2019-09-30 08:21:26 【问题描述】:

我正在使用DateFNS,我需要用它生成倒计时。 distanceInWordsToNow 仅输出大约 3 年,但我需要像 3 Years, 11 Months, 20 Days, 3 Hours, 2 Minutes 这样的确切时间。如何使用 DateFNS 存档?

这是一个 CodePen 示例: https://codepen.io/anon/pen/qGajJB

脚本

todaysDateMin: dateFns.distanceInWordsToNow(new Date(2022, 6, 2, 0, 0, 15), addSuffix: true)

【问题讨论】:

在我看来,您可以使用 differenceInMinutes 然后通过除以一年中的分钟数等方式自行完成其余部分。 他们的追踪器中有一个open issue。此功能尚未实现,但您可以按照 Jeremy 的描述自行解决。该库具有differenceInYearsdifferenceInMonthsdifferenceInDays 等函数。您需要做的就是使用它们构建最终的字符串。将来,他们计划向distanceInWords 引入一个附加参数,以允许指定输出格式。 @Tom,如果使用纯 JS 实现解决方案,您可以吗?没有图书馆? 【参考方案1】:

date-fns v2 中的 formatDuration() 函数完全符合您的要求。

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

你甚至可以过滤它。

// 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

【讨论】:

对于这两个模块,我都会收到此错误:Module '"date-fns"' has no exported member 'formatDuration'.ts(2305)。在package.json 我们有"date-fns": "^2.0.1",所以它应该已经可用了。你知道是什么问题吗? 根据文档,formatDuration函数是在v2.14.0中增加的,所以更新库。 date-fns.org/v2.14.0/docs/formatDuration 这解决了问题,谢谢。【参考方案2】:

你可以试试这样的:

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$uPs`](fDate, now);
    if (t) 
      result.push(`$i===parts.length-1 ? 'and ' : ''$t $uP$t===1 ? '' : 's'`);
      if (i < parts.length)
        fDate = dateFns[`sub$uPs`](fDate, t);
    
  )
  return result.join(' ');


console.log(humanizeFutureToNow(new Date('2022-11-11')))
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js"&gt;&lt;/script&gt;

我们的想法是遍历您想要的所有时间段(并支持 date-fns 函数)并生成一个包含所有字符串的数组。为此,我们首先运行支持的differenceIn&lt;PARTGOESHERE&gt; 以获取时间distance,然后使用sub&lt;PARTGOESHERE&gt; 函数减去它。之后加入他们组成最终的字符串。

从这里您可以自定义和导出零件作为参数,以及输出中第一个字母的大写等。

这里也是一个lodash版本:

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$scParts`, fDate, now);
    if (t) 
      result.push(`$i===parts.length-1 ? 'and ' : ''$t $scPart$t===1 ? '' : 's'`);
      if (i < parts.length)
        fDate = _.invoke(dateFns, `sub$scParts`, 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>

【讨论】:

感谢您的示例和 lodash 建议。你会如何在 lodash 中做到这一点? 我清理了纯js版本并添加了一个lodash版本。它们非常接近,只是也许 lodash 更易读。如果您真正专注于该版本,可能会有更多增强功能。 我喜欢你能够构建循环而不是重复自己的方式(以及如何轻松地将其扩展到包括秒和毫秒)【参考方案3】:

使用以下 dateFns 函数获取组件,然后将它们与字符串连接在一起。

设 x 为较小的年份,y 为较大的年份 保存在 x 和 y 上调用的 differenceInYears,它给出了变量中的整数年 将 x 和 that 作为参数传递给 addYears,分配给 x

在 x 和 y 上调用 differenceInMonths,保存 在 x 上调用 addMonths 并保存月数

对 differenceInDays 和 addDays、differenceInHours 和 addHours 执行相同的操作 现在 x 距离 y 不到 60 分钟,所以调用 differenceInMinutes 就完成了(假设您的倒计时到分钟)。

这是您在 runkit.com 上运行的示例来说明该方法。

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);

【讨论】:

不错的方法:)

以上是关于带有年、月、日、小时和分钟的 date-fns 倒计时的主要内容,如果未能解决你的问题,请参考以下文章

SQL 计算时间差问题,要精确到天小时分钟.

用于组合日期的 SQL 表达式,例如年/月/日来自 1 日、小时/等。从第二

java中求一下2008年5月31日, 往前倒30天是哪天?

为啥日历值不同?

PHP如何获取日期时间格式“5月19日星期二下午1:24”的小时和分钟[重复]

java 日期