基于date-fns实现hh:ss(分钟百进制)格式任务时长计算优化
优化任务时长计算方案(hh:百进制分钟格式)
问题概述
开发个人时间日志工具,需将任务的start和end(Date对象)计算为hh:ss格式时长:
- hh:累计小时数(可超过24)
- ss:百进制分钟数(如15分钟=25,30分钟=50)
现有方案依赖date-fns的differenceInSeconds和intervalToDuration,存在冗余计算,需要优化。
方案一:基于date-fns的高效实现
直接计算总分钟数,拆分小时和剩余分钟后转换为百进制,避免intervalToDuration处理无关时间单位的开销:
import { differenceInMinutes } from "date-fns"; const zeroPad = (num) => String(num).padStart(2, '0'); const getDuration = (task) => { // 计算两个时间的总分钟差 const totalMinutes = differenceInMinutes(task.end, task.start); // 提取完整小时数 const hours = Math.floor(totalMinutes / 60); // 计算剩余分钟对应的百进制数值 const centiMinutes = Math.round(((totalMinutes % 60) * 100) / 60); return `${hours}:${zeroPad(centiMinutes)}`; };
优势
- 仅调用
differenceInMinutes一个date-fns函数,比原方案减少一次函数调用 - 跳过
intervalToDuration对年、月、日等无关单位的计算,逻辑更直接高效
方案二:原生JavaScript实现(无依赖)
如果想完全脱离库依赖,直接通过Date对象时间戳计算:
const zeroPad = (num) => String(num).padStart(2, '0'); const getDuration = (task) => { // 计算毫秒级时间差 const diffMs = task.end.getTime() - task.start.getTime(); // 转换为总分钟数 const totalMinutes = diffMs / (1000 * 60); const hours = Math.floor(totalMinutes / 60); const centiMinutes = Math.round(((totalMinutes % 60) * 100) / 60); return `${hours}:${zeroPad(centiMinutes)}`; };
优势
- 无外部依赖,性能最优
- 代码量与date-fns方案相当,无需额外引入库
方案验证
两种方案均能输出预期结果:
| 开始时间 | 结束时间 | 结果 |
|---|---|---|
| 2022年11月17日 08:00 | 2022年11月17日 09:15 | 1:25 |
| 2022年11月17日 08:00 | 2022年11月17日 11:45 | 3:75 |
| 2022年11月17日 08:00 | 2022年11月17日 08:30 | 0:50 |
| 2022年11月17日 08:00 | 2022年11月18日 11:00 | 27:00 |
注意事项
- 如果时间选择器仅支持15分钟步进,可去掉
Math.round(结果天然为整数);若允许任意分钟输入,Math.round可保证百进制数值的精度 - 原生方案需确保
task.start和task.end为有效Date对象,避免时间戳计算出错
内容的提问来源于stack exchange,提问作者Benjamin Dubé
相关产品推荐
相关产品推荐

