给定int值1807
,使用date-fns将其格式化为30:07
?
是的,我知道可以使用普通的js实现,但是否可以使用date-fns实现?
给定int值1807
,使用date-fns将其格式化为30:07
?
是的,我知道可以使用普通的js实现,但是否可以使用date-fns实现?
intervalToDuration
将以秒为单位(作为Interval
传递)转换为Duration
,然后按照OP所需的方式简化格式:import { intervalToDuration } from 'date-fns'
const seconds = 10000
intervalToDuration({ start: 0, end: seconds * 1000 })
// { hours: 2, minutes: 46, seconds: 40 }
对于提问者的需求:
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
编辑(2022-08-04):有人指出上面的简单代码不会给数字补零,因此最终结果将是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
中已经存在的直接帮助程序之一:formatDistanceToNow
/ formatDistanceToNowStrict
。 - Glenn 'devalias' Grant你可以使用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>
var helperDate = dateFns.addSeconds(new Date(0), seconds)
这段代码会将你的时区偏移量加到结果日期上,例如,如果你使用 hh:mm:ss
格式来格式化结果,那么 180
秒将产生 10:03:00
,而 240
秒将产生 10:04:00
,前提是你在一个 +10
的时区偏移量下。 - user1063287 const dateHelper: Date = addSeconds(new Date(0), duration);
const utcDate = zonedTimeToUtc(dateHelper, TIME_ZONE);
this.durationDisplay = format(addHours(utcDate, -1), 'HH:mm:ss');
- HasBert此函数将把秒转换成持续时间格式 hh:mm:ss,与 moment.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:
format((seconds * 1000), 'mm:ss')
如果需要同时去除时区小时偏移量,可以使用getTimezoneOffset(以分钟为单位):
let dt = new Date((seconds * 1000));
dt = addMinutes(dt, dt.getTimezoneOffset());
return format(dt, 'mm:ss');
1807
秒转换成 mm:ss
的精确示例而言,这种方法可行,但如果您想要处理小时数的话,它就无法胜任了。例如,将格式字符串更改为 hh:mm:ss
将会导致输出为 12:30:07
,即使在这种情况下小时数实际上应该是 0
。 - Glenn 'devalias' Grant在date-fns中似乎没有直接相当于moment.duration的功能...
我写了一个函数,可能对某些人有帮助。使用Date-fns.differenceInSeconds函数可以获取总秒数的差异。还有等效方法可用于毫秒、分钟等。 然后我使用原生JavaScript数学格式化这个值。
/**
* 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}`;
};
String.prototype.padStart()
:String(num).padStart(2, '0')
。 - Glenn 'devalias' Grant.filter(Boolean)
示例时吗?这会过滤掉任何虚假的结果(例如0
),因此如果您删除该行,则它们将被包括在内,并且将使用上面的1807
秒作为格式化结果00:30:07
。然而,您最好使用下面的“自定义格式”示例,因为随着发现边缘情况,我的原始解决方案越来越像 hacky。在“自定义格式”示例中,zero:true
布尔值控制是否包括0
(例如,1800
秒将给出30:00
或30
取决于此标志)。 - Glenn 'devalias' Grant