WinCC Ticks与C# DateTime双向转换的精度问题排查
解决WinCC Flexible Ticks与C# DateTime双向转换的精度问题
问题根源
你的转换逻辑中,DateTimeToSiemensTime方法的计算公式错误,这是导致双向转换出现误差的核心原因:
- WinCC的Time_ms(Ticks)单位是1e-6天(即1个Tick等于百万分之一天)
- C#
TimeSpan.Ticks的单位是100纳秒,1天 = 86400秒 = 8.64×10¹¹个C# Tick - 正确转换公式应为:
WinCC Tick = (C# TimeSpan Ticks) / 864000.0,而非原代码中的除以1e6
此外,大数值用double运算会存在微小精度损耗,但只要公式正确,误差会缩小到可忽略的级别。
修正后的代码
1. WinCC Ticks转C# DateTime
保留原有逻辑,补充时间一致性处理避免时区问题:
DateTime SiemensTimeToDateTime(double siemensTime) { // WinCC固定起始时间:1899-12-30 00:00:00 var startDateTime = new DateTime(1899, 12, 30, 0, 0, 0, DateTimeKind.Utc); // 1个WinCC Tick对应1e-6天,直接转换为时间跨度 var timeSpan = TimeSpan.FromDays(siemensTime / 1_000_000d); return startDateTime.Add(timeSpan); }
2. C# DateTime转WinCC Ticks
修正核心计算公式,同时统一时区避免偏差:
double DateTimeToSiemensTime(DateTime dateTime) { var startDateTime = new DateTime(1899, 12, 30, 0, 0, 0, DateTimeKind.Utc); // 统一转换为UTC时间,避免本地时区差异影响计算 if (dateTime.Kind != DateTimeKind.Utc) dateTime = dateTime.ToUniversalTime(); var timeSpan = dateTime.Subtract(startDateTime); // 正确转换:1天=8.64e11 C# Tick,1 WinCC Tick=1e-6天 → 8.64e11 / 1e6 = 864000 return timeSpan.Ticks / 864000.0; }
验证测试
用你的测试值验证:
double mainTick = 45590722754.8727; // 对应日志中的"2024-10-25 17:20:46" DateTime dt = SiemensTimeToDateTime(mainTick); double calcTick = DateTimeToSiemensTime(dt); double diff = calcTick - mainTick; // 此时diff会趋近于0,误差在double精度范围内(约1e-12级别,完全可忽略)
额外优化建议
如果需要彻底消除浮点精度损耗,可以将WinCC Tick转换为整数微秒处理:
- 1 WinCC Tick = 86.4微秒(1e-6天 = 0.0864秒 = 86.4微秒)
- 用64位整数存储微秒数进行双向转换,完全规避浮点运算的精度问题。
内容的提问来源于stack exchange,提问作者nub
相关产品推荐
相关产品推荐

