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

JavaScript进度条时间差百分比计算异常:超100%问题排查求助

问题:进度条百分比超过100%的异常情况

我正在开发一个基于时间差百分比展示的进度条,但遇到了问题:当起始日期为今日、过期日期为明日时,计算出的百分比会超过100%,这不符合预期。以下是我的代码,恳请帮忙检查和评审,任何反馈都将不胜感激,谢谢。

export default function TrackBar({ storageDate, expiryDate }) {

  // 转换日期为时间戳(毫秒级)
  function epoch(date) {
    return Date.parse(date)
  }

  // 起始日期转时间戳
  const storageTimestamp = epoch(storageDate)
  // 过期日期转时间戳
  const expiryTimestamp = epoch(expiryDate)
  // 当前日期转时间戳
  const dateToday = new Date()
  const todayTimestamp = epoch(dateToday)

  const progress = Math.floor((todayTimestamp - storageTimestamp)/(expiryTimestamp - storageTimestamp)* 100)
  console.log(progress)

  let color = "#CF5C5C";

  if (progress <= 25) {
    color = "#158463";
  } else if (progress <= 50) {
    color = "#158463"
  } else if (progress <= 75) {
    color = "#FD9345"
  } else if (progress <= 100) {
    color = "#CF5C5C"
  }

  const progressStyles = {
    width: `${progress}%`,
    backgroundColor: `${color}`,
  };
  
  if (!progress){
    return (
      <h1>Loading......</h1>
    )
  }

  return (
    <>
      <div className="trackBar">
        <div className="trackBar__inner" style={progressStyles}></div>
      </div>
    </>
  )
}

问题分析与修复方案

1. 核心问题:未限制进度范围

当当前时间超过过期时间时,todayTimestamp - storageTimestamp会大于expiryTimestamp - storageTimestamp,导致计算出的progress超过100。即使起始日期是今日、过期日期是明日,只要当前时间走到明日,就会触发这个问题。

2. 修复步骤

(1)强制限制进度在0-100之间

修改progress的计算逻辑,用Math.min和Math.max把值限定在合理范围内:

const progress = Math.floor(
  Math.min(
    Math.max(
      ((todayTimestamp - storageTimestamp) / (expiryTimestamp - storageTimestamp)) * 100,
      0
    ),
    100
  )
);

(2)处理无效日期边界

如果过期日期不晚于起始日期(比如传参错误),分母会为负数或0,导致计算异常。需要提前判断并处理:

let progress = 0;
if (expiryTimestamp > storageTimestamp) {
  progress = Math.floor(
    Math.min(
      Math.max(
        ((todayTimestamp - storageTimestamp) / (expiryTimestamp - storageTimestamp)) * 100,
        0
      ),
      100
    )
  );
} else {
  // 过期日期早于等于起始日期,直接标记为100%(已过期)
  progress = 100;
}

(3)优化颜色判断逻辑

原代码中<=25和<=50的颜色重复,可以合并条件减少冗余:

let color = "#CF5C5C";
if (progress <= 50) {
  color = "#158463";
} else if (progress <= 75) {
  color = "#FD9345";
}
// 剩余情况(76%-100%)使用默认红色

(4)修正Loading判断逻辑

原代码中if (!progress)会在进度为0时也显示Loading,这是错误的。应该判断日期是否有效(是否转换为合法时间戳):

if (isNaN(storageTimestamp) || isNaN(expiryTimestamp)) {
  return <h1>Loading......</h1>;
}

修复后的完整代码

export default function TrackBar({ storageDate, expiryDate }) {

  // 转换日期为时间戳(毫秒级)
  function epoch(date) {
    return Date.parse(date)
  }

  // 起始日期转时间戳
  const storageTimestamp = epoch(storageDate)
  // 过期日期转时间戳
  const expiryTimestamp = epoch(expiryDate)
  // 当前日期转时间戳
  const dateToday = new Date()
  const todayTimestamp = epoch(dateToday)

  let progress = 0;
  if (expiryTimestamp > storageTimestamp) {
    progress = Math.floor(
      Math.min(
        Math.max(
          ((todayTimestamp - storageTimestamp) / (expiryTimestamp - storageTimestamp)) * 100,
          0
        ),
        100
      )
    );
  } else {
    progress = 100;
  }
  console.log(progress)

  let color = "#CF5C5C";
  if (progress <= 50) {
    color = "#158463";
  } else if (progress <= 75) {
    color = "#FD9345";
  }

  const progressStyles = {
    width: `${progress}%`,
    backgroundColor: `${color}`,
  };
  
  if (isNaN(storageTimestamp) || isNaN(expiryTimestamp)) {
    return <h1>Loading......</h1>;
  }

  return (
    <>
      <div className="trackBar">
        <div className="trackBar__inner" style={progressStyles}></div>
      </div>
    </>
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 00:05:25