如何在C#.Net中将DateTime值四舍五入到最近的200毫秒?
问题:将DateTime四舍五入到最近的200毫秒
我正在开发一个C#.Net应用,需要将部分DateTime值四舍五入到最近的200毫秒。我已编写如下代码:
public static DateTime RoundToTheTwoHundredthMillisecond(DateTime dt) { var ms = dt.Millisecond; var s = dt.Second; var m = dt.Minute; var h = dt.Hour; var d = dt.Day; var M = dt.Month; var y = dt.Year; if (ms >= 900 && ms < 1000) ms = 1000; if (ms >= 700 && ms < 900) ms = 800; if (ms >= 500 && ms < 700) ms = 600; if (ms >= 300 && ms < 500) ms = 400; if (ms >= 100 && ms < 300) ms = 200; if (ms >= 0 && ms < 100) ms = 0; // 1000 is an invalid millisecond. We need to round up a second. Use AddSeconds so it will automatically roll up should we be 1 second away from a new minute, 1 minute away from a new hour...etc...leap years and months are handled also.... if (ms == 1000) { return new DateTime(y, M, d, h, m, s, 0, dt.Kind).AddSeconds(1); } else { return new DateTime(y, M, d, h, m, s, ms, dt.Kind); } }
我认为这段代码可能可行,但想请教是否有更可靠的实现方法?另外,是否需要为此编写单元测试?(担心测试编写也会出现疏漏)
优化实现方案
你的代码逻辑是没问题的,但多个if判断显得有些繁琐,而且可以通过数学计算来简化逻辑,同时保证可靠性。核心思路是把时间转换为当天的总毫秒数,对200毫秒的间隔做四舍五入,再转换回DateTime——利用DateTime的内置方法自动处理进位(跨秒、跨分钟甚至跨年都不用手动管),代码更简洁也更不容易出错:
public static DateTime RoundToNearest200Ms(DateTime dt) { // 计算从当天零点到当前时间的总毫秒数 long totalMilliseconds = (long)(dt - dt.Date).TotalMilliseconds; // 四舍五入到最近的200毫秒间隔 long roundedMs = (long)Math.Round(totalMilliseconds / 200.0) * 200; // 重新构建DateTime,保留原有的Kind信息 return dt.Date.AddMilliseconds(roundedMs).SpecifyKind(dt.Kind); }
为什么这个方案更可靠?
- 避免了手动枚举毫秒区间的
if判断,减少了逻辑疏漏的可能 Math.Round会自动处理四舍五入规则,比如900毫秒会被计算为1000毫秒(即1秒),AddMilliseconds会自动把这1000毫秒转换为1秒,跨秒、跨分钟这类场景(比如59秒950毫秒进位到下一分钟0秒0毫秒)也能自动处理- 完整保留了原DateTime的
Kind属性,避免时区相关的问题
关于单元测试:非常有必要!
时间处理的边界情况特别多,很容易踩坑,所以单元测试是必须的。你可以针对以下关键场景编写测试用例:
- 基础边界值:
- 输入
00:00:00.099→ 应该返回00:00:00.000 - 输入
00:00:00.100→ 应该返回00:00:00.200 - 输入
00:00:00.899→ 应该返回00:00:00.800 - 输入
00:00:00.900→ 应该返回00:00:01.000
- 输入
- 跨时间单位场景:
- 输入
00:00:59.950→ 应该返回00:01:00.000 - 输入
23:59:59.950→ 应该返回次日的00:00:00.000
- 输入
- DateTime.Kind测试:
- 测试
Utc、Local、Unspecified三种Kind的输入,确保输出的Kind和输入一致
- 测试
- 刚好命中200毫秒间隔的情况:
- 输入
00:00:00.200→ 返回自身,验证不会被错误修改
- 输入
这些测试用例可以覆盖大部分容易出错的场景,确保你的方法在各种情况下都能正确工作。
内容的提问来源于stack exchange,提问作者Obbles
相关产品推荐
相关产品推荐

