使用 date-fns 格式化持续时间(从秒开始)



给定的整数值1807,格式使用date-fns30:07

是的,我知道这可以用香草 js 实现,但这可以使用 date-fns 吗?

根据 date-fns/date-fns#229 (comment) 中的示例代码,我们现在可以使用intervalToDuration将秒(作为Interval传递)转换为Duration,然后可以根据 OP 的需要进行简化格式:

import {  intervalToDuration } from 'date-fns'
const seconds = 10000
intervalToDuration({ start: 0, end: seconds * 1000 })
// { hours: 2, minutes: 46, seconds: 40 }

因此,对于OP的需求:

import {  intervalToDuration } from 'date-fns'
const seconds = 1807
const duration = intervalToDuration({ start: 0, end: seconds * 1000 })
// { minutes: 30, seconds: 7 }
const formatted = `${duration.minutes}:${duration.seconds}`
// 30:7

Edit (2022-08-04):有人指出,上述简单的代码不会 0 填充数字,因此您最终会得到30:7而不是30:07。可以使用String.prototype.padStart()实现此填充,如下所示:

import {  intervalToDuration } from 'date-fns'
const seconds = 1807
const duration = intervalToDuration({ start: 0, end: seconds * 1000 })
// { minutes: 30, seconds: 7 }
const zeroPad = (num) => String(num).padStart(2, '0')
const formatted = `${zeroPad(duration.minutes)}:${zeroPad(duration.seconds)}`
// 30:07

还有人指出,如果Interval超过 60 分钟,它将开始在Duration内递增hours,上面的代码不会显示。因此,这是另一个稍微复杂的示例来处理这种情况以及zeroPad情况:

import {  intervalToDuration } from 'date-fns'
const seconds = 1807
const duration = intervalToDuration({ start: 0, end: seconds * 1000 })
// { minutes: 30, seconds: 7 }
const zeroPad = (num) => String(num).padStart(2, '0')
const formatted = [
duration.hours,
duration.minutes,
duration.seconds,
]
.filter(Boolean)
.map(zeroPad)
.join(':')
// 30:07

GitHub上还有一个问题,询问如何将自定义格式与formatDuration一起使用,这表明目前唯一的方法是提供自定义Locale。GitHub 用户@marselmustafin提供了使用此解决方法的示例。遵循相同的模式,我们可以大致实现OP所需的功能,如下所示:

import { intervalToDuration, formatDuration } from "date-fns";
const seconds = 1807;
const duration = intervalToDuration({ start: 0, end: seconds * 1000 });
// { minutes: 30, seconds: 7 }
const zeroPad = (num) => String(num).padStart(2, "0");
const formatted = formatDuration(duration, {
format: ["minutes", "seconds"],
// format: ["hours", "minutes", "seconds"],
zero: true,
delimiter: ":",
locale: {
formatDistance: (_token, count) => zeroPad(count)
}
});
// 30:07

下面是简单的实现:

import { formatDistance } from 'date-fns'
const duration = s => formatDistance(0, s * 1000, { includeSeconds: true })
duration(50) // 'less than a minute'
duration(1000) // '17 minutes'

这基本上与:

import moment from 'moment'    
const duration = s => moment.duration(s, 'seconds').humanize()
duration(50) // 'a minute'
duration(1000) // '17 minutes'

您可以使用 date-fns 通过简单地修改中间帮助程序日期来执行此操作。使用new Date( 0 )将获得设置为 1970 年 1 月 1 日 00:00:00 UTC 的日期。然后,您可以使用 date-fns 中的addSeconds来添加相关的秒数(实际上您可以使用本机日期setTime( 1000 * seconds ))。格式化此内容的分钟和秒将为您提供所需的结果。

var input = document.getElementById('seconds');
var output = document.getElementById('out');
output.innerText = formattedTime(input.value);
input.addEventListener('input', function() {
output.innerText = formattedTime(input.value);
});
function formattedTime(seconds) {
var helperDate = dateFns.addSeconds(new Date(0), seconds);
return dateFns.format(helperDate, 'mm:ss');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.26.0/date_fns.min.js"></script>
<input type="number" id="seconds" value="1807">
<pre id="out"></pre>

此函数会将秒转换为持续时间格式 hh:mm:ss,其模拟持续时间(以时刻为单位.js

import { addHours, getMinutes, getHours, getSeconds } from 'date-fns';
export const convertToDuration = (secondsAmount: number) => {
const normalizeTime = (time: string): string =>
time.length === 1 ? `0${time}` : time;
const SECONDS_TO_MILLISECONDS_COEFF = 1000;
const MINUTES_IN_HOUR = 60;
const milliseconds = secondsAmount * SECONDS_TO_MILLISECONDS_COEFF;
const date = new Date(milliseconds);
const timezoneDiff = date.getTimezoneOffset() / MINUTES_IN_HOUR;
const dateWithoutTimezoneDiff = addHours(date, timezoneDiff);
const hours = normalizeTime(String(getHours(dateWithoutTimezoneDiff)));
const minutes = normalizeTime(String(getMinutes(dateWithoutTimezoneDiff)));
const seconds = normalizeTime(String(getSeconds(dateWithoutTimezoneDiff)));
const hoursOutput = hours !== '00' ? `${hours}:` : '';
return `${hoursOutput}${minutes}:${seconds}`;
};

只需使用来自 date-fns格式,如下所示:

format((seconds * 1000), 'mm:ss')

如果还需要删除时区小时偏移量,getTimezoneOffset(以分钟为单位)可以使用:

let dt = new Date((seconds * 1000));
dt = addMinutes(dt, dt.getTimezoneOffset());
return format(dt, 'mm:ss');

在 date-fns 中似乎没有直接等同于 moment.duration...

我写的这个函数可能会帮助某人。Date-fns.differenceInSeconds用于获取以秒为单位的总差值。毫秒、分钟等有等效的方法。 然后我使用香草js数学来格式化它

/**
* calculates the duration between two dates.
* @param {date object} start The start date.
* @param {date object} finish The finish date.
* @return {string} a string of the duration with format 'hh:mm'
*/
export const formatDuration = (start, finish) => {
const diffTime = differenceInSeconds(finish, start);
if (!diffTime) return '00:00'; // divide by 0 protection
const minutes = Math.abs(Math.floor(diffTime / 60) % 60).toString();
const hours = Math.abs(Math.floor(diffTime / 60 / 60)).toString();
return `${hours.length < 2 ? 0 + hours : hours}:${minutes.length < 2 ? 0 + minutes : minutes}`;
};

最新更新