TimeSpan.ParseExact解析超59秒/分的自定义格式时间有何解决方案?
解决方案
最优的实现方案是将用户自定义格式动态转换为正则表达式,匹配提取各时间单位数值后累加计算总时长,完全适配动态可变的格式需求,不需要硬编码拆分规则。
实现逻辑
- 预定义时间单位和毫秒的换算关系,同时适配毫秒位的不同位数规则
- 遍历用户配置的时间格式字符串,生成对应的匹配正则,同时记录每个捕获组对应的单位信息:
- 连续的d/h/m/s/f字符替换为
(\d+)捕获组,记录单位类型和连续长度(用于毫秒位换算) - 非时间单位的字面量字符(包括转义后的分隔符、自定义文本)做正则转义后保留
- 连续的d/h/m/s/f字符替换为
- 用户输入内容用生成的正则匹配,依次取出每个捕获组的数值,乘以对应单位的换算值累加得到总毫秒数
示例代码
using System.Text.RegularExpressions; public static class DynamicTimeParser { // 时间单位对应的毫秒换算系数 private static readonly Dictionary<char, long> _unitBaseMs = new() { {'d', 86400000 }, // 天 {'h', 3600000 }, // 小时 {'m', 60000 }, // 分钟 {'s', 1000 }, // 秒 {'f', 1 } // 毫秒 }; public static bool TryParse(string input, string format, out long totalMs) { totalMs = 0; var regexPattern = ""; var captureUnits = new List<(char unit, int length)>(); int i = 0; while (i < format.Length) { char c = format[i]; // 处理转义字符 if (c == '\\') { regexPattern += Regex.Escape(format[i+1].ToString()); i += 2; continue; } // 识别连续的时间单位符 if (_unitBaseMs.ContainsKey(c)) { int len = 1; while (i + len < format.Length && format[i+len] == c) len++; regexPattern += @"(\d+)"; captureUnits.Add((c, len)); i += len; continue; } // 普通字面量转义 regexPattern += Regex.Escape(c.ToString()); i++; } // 完整匹配正则 var regex = new Regex($"^{regexPattern}$"); var match = regex.Match(input); if (!match.Success) return false; // 累加计算总毫秒 for (int j = 0; j < captureUnits.Count; j++) { var (unit, len) = captureUnits[j]; if (!long.TryParse(match.Groups[j+1].Value, out long val)) return false; long ms = val * _unitBaseMs[unit]; // 处理毫秒位不足3位的情况 if (unit == 'f') ms *= (long)Math.Pow(10, 3 - len); totalMs += ms; } return true; } }
调用方法
直接替换你原有代码中的TryParseTime方法即可:
static bool TryParseTime(string time, string format, out long parsed) { return DynamicTimeParser.TryParse(time, format, out parsed); }
方案优势
- 完全兼容你现有支持的所有自定义格式,包括带自定义文本的格式如
ss\s\. fff mils\. - 所有单位的数值都支持超过进位阈值(比如90分钟、100秒都可以正常解析)
- 不需要依赖第三方库,纯原生实现,性能稳定
内容的提问来源于stack exchange,提问作者Pakoco
相关产品推荐
相关产品推荐

