You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何计算任务平均完成时长并绘制月度折线图?

问题描述

需要创建一张按月份分组的平均任务完成时长折线图,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 12:45:00