如何计算任务平均完成时长并绘制月度折线图?
问题描述
需要创建一张按月份分组的平均任务完成时长折线图,X轴展示月份,Y轴衡量完成时长。原始数据格式如下:
var vals = [ { x: "Jan/2025", y: "5 16:00:00" }, { x: "Feb/2025", y: "23 17:00:00" }, { x: "Mar/2025", y: "41 23:13:20" }, ]
其中"41 23:13:20"对应41天23小时13分20秒。尝试将时间转换为毫秒用于绘图时,大数被转为科学计数法导致精度丢失,希望Y轴能动态适配数值范围。
当前实现代码如下:
依赖引入
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/modules/data.js"></script> <script src="https://code.highcharts.com/modules/accessibility.js"></script> <script src="https://code.highcharts.com/modules/exporting.js"></script> <div id="container" style="height: 400px; margin: 0 auto"></div>
逻辑代码
$(function () { function toMilli(timeStr) { // Split the input string into days, hours, minutes, and seconds const [days, time] = timeStr.split(" ") const [hours, minutes, seconds] = time.split(":") // Convert each part to milliseconds const daysInMillis = parseInt(days) * 24 * 60 * 60 * 1000 const hoursInMillis = parseInt(hours) * 60 * 60 * 1000 const minutesInMillis = parseInt(minutes) * 60 * 1000 const secondsInMillis = parseInt(seconds) * 1000 // Return the total time in milliseconds return daysInMillis + hoursInMillis + minutesInMillis + secondsInMillis } var vals = [ { x: "Jan/2025", y: "5 16:00:00" }, { x: "Feb/2025", y: "23 17:00:00" }, { x: "Mar/2025", y: "41 23:13:20" }, ] var rowData = vals.map((val) => [val.x, toMilli(val.y)/(1000*60*60*24)]) var rows = [ [null, '2025'], ...rowData, ] Highcharts.chart("container", { chart: { type: 'line' }, yAxis: { title: { text: "Days" } }, title: { text: "Average Time to Complete", align: "left", }, data: { rows: rows }, }) })
技术解决方案
1. 规避毫秒精度丢失:直接转换为天数小数
跳过毫秒转换环节,直接将时分秒转为天的小数部分,数值更小不会触发科学计数法,同时保留精度:
function toDays(timeStr) { const [daysStr, timeStrPart] = timeStr.split(" "); const [hours, minutes, seconds] = timeStrPart.split(":").map(Number); const days = Number(daysStr); const hoursToDays = hours / 24; const minutesToDays = minutes / (24 * 60); const secondsToDays = seconds / (24 * 60 * 60); return days + hoursToDays + minutesToDays + secondsToDays; }
用这个函数替代原toMilli,直接得到精确的天数数值。
2. 配置Y轴动态适配与友好格式化
让Highcharts自动适配数值范围,同时把Y轴标签和tooltip格式化为用户易读的“天+时分”形式:
Highcharts.chart("container", { chart: { type: 'line' }, yAxis: { title: { text: "完成时长" }, // 自动适配数据范围,不强制显示首尾刻度 startOnTick: false, endOnTick: false, // 格式化Y轴标签 labels: { formatter: function() { const totalDays = this.value; const days = Math.floor(totalDays); const hours = Math.round((totalDays - days) * 24); return hours > 0 ? `${days}天${hours}时` : `${days}天`; } } }, title: { text: "平均任务完成时长", align: "left", }, tooltip: { // 鼠标悬浮显示精确时长 formatter: function() { const totalDays = this.y; const days = Math.floor(totalDays); const remaining = (totalDays - days) * 24; const hours = Math.floor(remaining); const minutes = Math.round((remaining - hours) * 60); return `<b>${this.x}</b><br/>平均时长: ${days}天${hours}时${minutes}分`; } }, data: { rows: rows }, })
3. 优化数据映射流程
修改数据转换逻辑,使用新的toDays函数:
var rowData = vals.map((val) => [val.x, toDays(val.y)]);
这样处理后,既解决了大数精度丢失问题,Y轴也能根据数据范围自动调整,同时展示的时长格式更符合用户阅读习惯。
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

