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

JavaScript格式化avg_runtime字符串并实现Material UI DataGrid正确排序

问题描述

初始问题

在将字符串格式化为可用于Material UI DataGrid的有效可排序类型时遇到问题,涉及字段为avg_runtime。API返回数据包含两种格式的运行时长字符串:

  • 无天数格式:0:05:12.026100
  • 带天数格式:9 days, 17:30:02.813297

后端已新增avg_runtime_seconds字段,返回以秒为单位的十进制数值,但前端在DataGrid中排序时,带天数的字符串出现排序异常(如9 days, 17:30:02.813297与11 days, 2:43:52.300138排序顺序错误)。尝试使用new Date(${x.avg_runtime}).toDateString()转换时,返回Invalid Date。

API返回示例:

{
"data": [
    {
        "id": "01",
        "avg_runtime": "0:05:12.026100",
        "avg_runtime_seconds": 312.0261,
        "file_name": "myFile1"
    },
    {
        "id": "02",
        "avg_runtime": "0:10:03.936321",
        "avg_runtime_seconds": 603.936321,
        "file_name": "myFile2"
    }
  ]
}

当前前端API调用的格式化逻辑:

async function getData() {
  await axios
      .get(`https://myapi.com/${ runmode }/products`, {
      headers: {
          'Content-Type': 'application/json'
      }
      })
      .then((response) =>{
          var this_data = response.data.data;
          setData(
              this_data.map((x) => {
                  return {
                      id: parseInt(`${x.product_id}`),
                      file_name: `${x.file_name}`,
                      avg_runtime: `${x.avg_runtime}`,
                      avg_runtime_seconds: `${x.last_rundate}`   
                  }
              })
          );
          setValidationList(
              this_data.map((x) => x.product_id)
          )
          setLoadingData(false);
      });
}

更新后问题

按照建议使用Value Getter后,即使avg_runtime_seconds为6位小数的数值,排序时仍未按整体数值比较,而是按字符位置排序(如9天17小时对应的秒数与2小时对应的秒数排序异常)。


解决方案

1. 修复前端数据类型错误

当前代码中存在明显笔误:avg_runtime_seconds被错误赋值为${x.last_rundate},且用模板字符串转为了字符串类型,这是导致按字符排序的核心原因。修正如下:

setData(
  this_data.map((x) => {
    return {
      id: parseInt(x.product_id),
      file_name: x.file_name,
      avg_runtime: x.avg_runtime,
      // 确保avg_runtime_seconds为数值类型,而非字符串
      avg_runtime_seconds: Number(x.avg_runtime_seconds)
    };
  })
);

2. 配置DataGrid列的排序规则

在DataGrid的列定义中,指定avg_runtime列使用avg_runtime_seconds数值字段进行排序,同时保留原字符串的显示格式:

const columns = [
  // 其他列配置
  {
    field: 'avg_runtime',
    headerName: '平均运行时间',
    // 显示原始时长字符串
    valueGetter: (params) => params.row.avg_runtime,
    // 强制使用数值字段进行排序
    sortAccessor: (params) => params.row.avg_runtime_seconds,
    // 可选:自定义格式化显示(统一格式)
    valueFormatter: (params) => {
      return formatSecondsToDuration(params.row.avg_runtime_seconds);
    }
  },
  // 可选:显示秒数字段,设置为数值类型确保排序正确
  {
    field: 'avg_runtime_seconds',
    headerName: '运行时长(秒)',
    type: 'number'
  }
];

3. 自定义时长解析/格式化工具函数(可选)

如果后端未返回avg_runtime_seconds,可以自行解析avg_runtime字符串为总秒数:

// 将时长字符串转为总秒数
function parseDurationToSeconds(durationStr) {
  let totalSeconds = 0;
  // 处理带天数的格式
  const dayMatch = durationStr.match(/(\d+) days,/);
  if (dayMatch) {
    totalSeconds += parseInt(dayMatch[1]) * 24 * 3600;
    // 提取时间部分并拆分
    const [hours, minutes, seconds] = durationStr.split(', ')[1].split(':');
    totalSeconds += parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseFloat(seconds);
  } else {
    // 处理无天数的HH:MM:SS.sss格式
    const [hours, minutes, seconds] = durationStr.split(':');
    totalSeconds += parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseFloat(seconds);
  }
  return totalSeconds;
}

// 将总秒数转回易读的时长格式
function formatSecondsToDuration(totalSeconds) {
  const days = Math.floor(totalSeconds / (24 * 3600));
  const remainingSeconds = totalSeconds % (24 * 3600);
  const hours = Math.floor(remainingSeconds / 3600);
  const minutes = Math.floor((remainingSeconds % 3600) / 60);
  const seconds = remainingSeconds % 60;

  let durationStr = '';
  if (days > 0) {
    durationStr += `${days} days, `;
  }
  durationStr += `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toFixed(6)}`;
  return durationStr;
}

内容的提问来源于stack exchange,提问作者gwydion93

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 06:35:17