如何让C#与SQL Server的毫秒转DateTime结果保持一致?
如何让C#的毫秒时间戳转换结果与SQL Server保持一致?
问题分析
你遇到的核心问题是:同一个UTC毫秒时间戳1563527339733,在SQL Server里转换后得到的秒数是09:08:59,但你的C#代码因为用了Math.Round做四舍五入,结果变成了09:09:00,两者逻辑不一致导致结果偏差。
具体来看两种转换逻辑的差异:
- SQL Server:用整数除法
@UTC / 1000直接截断毫秒部分的小数,只保留整数秒,再加上剩余的毫秒数,完全不会触发进位; - 你的C#代码:
Math.Round(milisecond / 1000d)会把1563527339.733四舍五入成1563527340,直接让秒数进了一位。
解决方案
要让C#和SQL的结果一致,只需要把C#的转换逻辑改成截断小数(向下取整),以下两种方式都可以:
方式1:拆分秒和毫秒(完全对齐SQL逻辑)
直接模仿SQL的处理步骤,把毫秒数拆成整数秒和剩余毫秒,分别添加到基准时间上:
public static DateTime ConvertMilisecondToDateTimeUTC(long milisecond) { // 整数除法截断小数,和SQL的@UTC / 1000逻辑完全一致 long totalSeconds = milisecond / 1000; int remainingMs = (int)(milisecond % 1000); // 指定DateTimeKind.Utc,避免时区带来的额外问题 var utcBaseTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); return utcBaseTime.AddSeconds(totalSeconds).AddMilliseconds(remainingMs); }
方式2:用Math.Floor向下取整
如果不想拆分秒和毫秒,也可以用Math.Floor直接对秒数向下取整,效果和整数除法一致:
public static DateTime ConvertMilisecondToDateTimeUTC(long milisecond) { var utcBaseTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); // 向下取整,舍去毫秒部分的小数,不会触发进位 return utcBaseTime.AddSeconds(Math.Floor(milisecond / 1000d)); }
测试验证
修改后调用代码:
DateTime dtCheck = DateTimeHelper.ConvertMilisecondToDateTimeUTC(1563527339733); string test = dtCheck.ToString("HH:mm:ss");
得到的结果就是09:08:59,和SQL Server的输出完全匹配。
内容的提问来源于stack exchange,提问作者Hong Van Vit




