DateTime.ParseExact转换失败:单数字小时引发无效日期时间错误
解决DateTime.ParseExact解析单小时位时间字符串的错误
问题描述
String was not recognized as a valid DateTime. stack: at System.DateTimeParse.ParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style)
发现仅当尝试将以单个0开头的时间字符串转换为DateTime时才会触发该错误。现有读取日志文件的脚本,需要判断日期是否在指定范围内,但日志行数过多,不想用正则表达式逐行检查小时部分的格式,也不愿修改日志或日志生成逻辑,求正确转换此类字符串的方法。
相关代码
string serverPath = @"\\" + serverName; string logNameFull = logName + ".txt"; string partialPath = @"\build\logs\"; string combinedPath2 = partialPath + logNameFull; Uri serverUri = new Uri(serverPath + combinedPath2); string finalPath = serverUri.LocalPath; DataTable dataTable = ReadDataTable(finalPath); foreach (DataRow row in dataTable.Rows) { try { if (Regex.IsMatch((row[startTimeHeader]).ToString(), @"^\d+")) //过滤非日期格式的日志行 { string tmpStartDT = (row[startTimeHeader]).ToString(); startDate = DateTime.ParseExact(tmpStartDT, "MM/dd/yyyy HH:mm:ss", provider); //出错行 } } catch (Exception ex) { Console.WriteLine("Caught exception for row: {0} CName:{1} on line close to:{2} server:{3} logname:{4} startDate:{5}", row.ToString(), cName, debug_i, serverName, logName, row[startTimeHeader]); Console.WriteLine("Message: " + ex.Message + " stack:" + ex.StackTrace); } } // foreach
控制台错误输出
Caught exception for row: System.Data.DataRow CName:CopyLogFile on line close to:475 server:mach62 logname:ParseLogStats startDate:04/14/2024 0:38:07
对应日志行内容
04/14/2024 0:38:07 04/14/2024 0:38:13 Sun 00:00:06 6 Success v24.1 Incr Stage_M 0 967 0 0 0 0 0 0 0 I:\logs\Stage_.log Message: String was not recognized as a valid DateTime. stack: at System.DateTimeParse.ParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style) at System.DateTime.ParseExact(String s, String format, IFormatProvider provider) at BuildStatusVerification.BuildStatusVerification.ParseLogFile(String codeFreezeTime, String startTimeHeader, String serverName, String logName, String cName, String cValue, String field1, String comparison1, String val) in C:\BuildStatusVerification\BuildStatusVerification\BuildStatusVerification.cs:line 150
解决方案
核心问题是格式字符串"MM/dd/yyyy HH:mm:ss"要求小时为两位数字(HH是24小时制的两位格式),但日志中的小时是一位(比如0:38:07),同时日期和小时之间存在两个空格。解决方法是传入多个可能的格式字符串,让ParseExact自动尝试匹配任意一种:
修改出错行的代码为:
// 同时支持两位小时和一位小时的格式,注意空格数量对应日志格式 string[] formats = { "MM/dd/yyyy HH:mm:ss", "MM/dd/yyyy H:mm:ss" }; startDate = DateTime.ParseExact(tmpStartDT, formats, provider, DateTimeStyles.None);
说明
HH对应两位小时(00-23),H对应一位或两位小时(0-23)- 第二个格式中的
H(两个空格)对应日志中日期与小时之间的两个空格 - 使用
ParseExact的多格式重载,无需逐行预处理或修改日志,直接适配两种时间格式
这样就能同时解析正常两位小时和单小时位的时间字符串,满足需求。
内容的提问来源于stack exchange,提问作者Michele
相关产品推荐
相关产品推荐

