解析DateTime时触发System.ArgumentOutOfRangeException:Length不能小于0
解析DataGrid日期时间列时的DateTime.Parse异常问题
问题场景
要解析DataGrid中某列的日期时间数据,该列格式示例如下:
3:44 PM 22/02/2023 10:58 PM 17/02/2023
通过Debug.WriteLine测试,提取时间部分的代码看似正常,但调用DateTime.Parse时抛出异常:
System.ArgumentOutOfRangeException: 'Length cannot be less than zero. Arg_ParamName_Name'
原代码如下:
string dateText = trade.Date.ToString(); int indexM = dateText.IndexOf('M'); if (indexM >= 0) // Check if 'M' exists in the string { dateText = dateText.Substring(0, indexM + 1); // Include the 'M' } DateTime time = DateTime.Parse(dateText);
问题分析
- 文化设置不兼容:如果当前系统线程的文化不是英文体系,
DateTime.Parse默认无法识别AM/PM格式的时间字符串,会导致解析失败甚至抛出异常。 - 字符串提取逻辑隐患:仅通过
IndexOf('M')提取时间的方式不够健壮,若trade.Date.ToString()返回的字符串格式异常(比如多个M字符、M出现在非AM/PM位置),会导致提取的时间字符串格式无效。 - 空值/无效字符串未处理:若
trade.Date.ToString()返回空字符串或空白字符串,后续操作可能触发异常。
解决方案
方案1:指定文化信息解析
如果提取的时间字符串是XX:XX AM/PM格式,直接指定InvariantCulture即可让DateTime.Parse正确识别:
string dateText = trade.Date.ToString().Trim(); int indexM = dateText.IndexOf('M'); if (indexM >= 0) { dateText = dateText.Substring(0, indexM + 1).Trim(); } // 指定不变文化,确保识别AM/PM格式 DateTime time = DateTime.Parse(dateText, CultureInfo.InvariantCulture);
方案2:更健壮的时间提取+TryParse安全解析
通过分割字符串提取时间部分,并用DateTime.TryParse避免抛出异常:
string rawDateText = trade.Date.ToString().Trim(); if (string.IsNullOrWhiteSpace(rawDateText)) { // 处理空值或无效字符串,比如返回默认值或抛出明确异常 throw new InvalidOperationException("日期字符串为空或格式无效"); } // 按空格分割,取前两部分(时间+AM/PM) string[] parts = rawDateText.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); if (parts.Length >= 2) { string timeText = $"{parts[0]} {parts[1]}"; if (DateTime.TryParse(timeText, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime time)) { // 解析成功,使用time变量 } else { // 解析失败,添加自定义处理逻辑 } } else { // 字符串格式不符合预期,添加处理逻辑 }
方案3:使用ParseExact精准匹配格式
如果确定时间部分的格式固定为h:mm tt(12小时制+AM/PM),可以用ParseExact直接匹配,避免歧义:
string rawDateText = trade.Date.ToString().Trim(); // 提取包含AM/PM的前半段时间 int ttEndIndex = rawDateText.IndexOf('M') + 1; if (ttEndIndex > 0 && ttEndIndex <= rawDateText.Length) { string timeText = rawDateText.Substring(0, ttEndIndex).Trim(); DateTime time = DateTime.ParseExact(timeText, "h:mm tt", CultureInfo.InvariantCulture); }
内容的提问来源于stack exchange,提问作者SA_
相关产品推荐
相关产品推荐

