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

C#中DateTime与TimeSpan相加出现额外12小时问题求助

问题原因与解决方案

为什么会出现额外的12小时?

核心问题出在你用DateTime(日期时间点)来存储和累加时间段,这完全用错了类型!

DateTime.ParseExact解析"00:00:30"这种字符串时,会默认把它绑定到公元1年1月1日这个日期上,对应的时间点是0001-01-01 00:00:30。当你用"hh:mm:ss"格式化这个时间点时,hh是12小时制的格式符,午夜0点在12小时制里会被显示为12——这就是为什么你得到12:00:40的原因,本质是把凌晨0点的时间点当成了12小时制的午夜12点来显示。

另外,你把时间段存在文本框里再反复解析成DateTime的做法,本身就违背了类型设计的初衷:TimeSpan才是专门用来表示时间长度/时间段的类型,DateTime是用来表示具体的日期时间点的,两者不能混用。

怎么修复?

直接改用TimeSpan来存储累加的总时长,代码逻辑会清晰很多,也不会出现奇怪的格式化问题:

  1. 首先在你的窗体类里声明一个类级别的变量,用来保存累计时长:
// 初始化为0时长
private TimeSpan _totalElapsedTime = TimeSpan.Zero;
  1. 修改stopbutton_Click方法的逻辑,直接用TimeSpan累加,避免解析DateTime的坑:
public void stopbutton_Click(object sender, EventArgs e)
{
    stopTime.Text = DateTime.Now.ToString("hh:mm:ss");
    
    // 解析开始和结束时间为DateTime,这部分没问题
    DateTime dt1 = DateTime.ParseExact(startTime.Text, "hh:mm:ss", new DateTimeFormatInfo());
    DateTime dt2 = DateTime.ParseExact(stopTime.Text, "hh:mm:ss", new DateTimeFormatInfo());
    TimeSpan ts1 = dt2.Subtract(dt1);
    
    // 显示单次耗时,用TimeSpan的格式化字符串,避免歧义
    diffTime.Text = ts1.ToString(@"hh\:mm\:ss");
    
    // 直接累加总时长
    _totalElapsedTime += ts1;
    
    // 格式化显示总时长:
    // 如果总时长不会超过24小时,直接用TimeSpan的格式化
    totTime.Text = _totalElapsedTime.ToString(@"hh\:mm\:ss");
    
    // 如果需要支持超过24小时的累计(比如总时长25:30:00),用下面的写法:
    // totTime.Text = $"{(int)_totalElapsedTime.TotalHours:D2}:{_totalElapsedTime.Minutes:D2}:{_totalElapsedTime.Seconds:D2}";
}

额外说明

  • @"hh\:mm\:ss"是TimeSpan的正确格式化方式,因为:在格式化字符串里是特殊字符,需要转义;
  • 如果你的累计时长可能超过24小时,直接用TimeSpan.ToString(@"hh\:mm\:ss")只会显示0-23的小时数,这时候需要用TotalHours来获取累计的总小时数,再拼接分钟和秒;
  • 不要再用DateTime来处理时间段了,这会让你陷入各种日期和12/24小时制的坑,TimeSpan就是为这种场景而生的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:35:54