.NET:为什么TryParseExact在Hmm和Hmmss上失败?

我正在尝试使用DateTime.TryParseExact方法,而且我遇到了一个我无法得到的情况。 我有一些格式和一些主题要解析每个格式应完全匹配其中一种格式:

 var formats = new[] { "%H", "HH", "Hmm", "HHmm", "Hmmss", "HHmmss", }; var subjects = new[] { "1", "12", "123", "1234", "12345", "123456", }; 

然后我尝试解析它们并打印出结果:

 foreach(var subject in subjects) { DateTime result; DateTime.TryParseExact(subject, formats, CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out result); Console.WriteLine("{0,-6} : {1}", subject, result.ToString("T", CultureInfo.InvariantCulture)); } 

我得到以下内容:

 1 : 01:00:00 12 : 12:00:00 123 : 00:00:00 1234 : 12:34:00 12345 : 00:00:00 123456 : 12:34:56 

而我的问题是……为什么它在123和12345失败了? 不应该成为01:23:00和01:23:45吗? 我在这里想念的是什么? 我怎样才能让它像我期望的那样工作?


更新:所以,似乎我们可能已经弄清楚为什么这是失败的。 似乎H实际上抓住两个数字,然后只留下一个mm ,然后失败。 但是,有没有人对如何更改此代码有一个好主意,以便我得到我正在寻找的结果?

另一个更新:想想我现在找到了一个合理的解决方案。 添加它作为答案。 将在2天内接受它,除非其他人想出更好的一个。 谢谢您的帮助!

好的,所以我想我现在已经想到这一切了,感谢更多的阅读,实验和其他有用的答案。 发生的事情是, Hms实际上可以抓取两位数,即使其余格式没有足够的数字。 因此,例如格式为Hmm和数字123H将抓住12并且仅剩下3 。 并且mm需要两位数,所以它失败了。 忠达

所以,我的解决方案目前只使用以下三种格式:

 var formats = new[] { "%H", "Hm", "Hms", }; 

由于我的问题的其余代码保持不变,我将得到这样的结果:

 1 : 01:00:00 12 : 12:00:00 123 : 12:03:00 1234 : 12:34:00 12345 : 12:34:05 123456 : 12:34:56 

我认为应该是合理的和可接受的:)

0123 012345

我猜它在找到一串这样的数字时会查找2/4/6的长度。 123应该是AM还是PM? 0123并不像那样含糊不清。

如果不在自定义格式模式中使用日期或时间分隔符,请使用provider参数的不变区域性和每个自定义格式说明符的最宽格式。 例如,如果要在模式中指定小时数,请指定更宽的forms“HH”,而不是更窄的forms,“H”

引用: http : //msdn.microsoft.com/en-us/library/ms131044.aspx

正如其他人所指出的,H是模棱两可的,因为它意味着每天10小时,而HH是12

引用MSDN的使用单一自定义格式说明符

自定义日期和时间格式字符串由两个或多个字符组成。 例如,如果格式字符串仅包含说明符h,则格式字符串将被解释为标准日期和时间格式说明符。 但是,在这种特殊情况下,抛出exception是因为没有标准的日期和时间格式说明符。

要使用单个自定义日期和时间格式说明符,请在日期和时间说明符之前或之后包含空格,或者在单个自定义日期和时间说明符之前包含百分比(%)格式说明符。 例如,格式字符串“h”和“%h”被解释为自定义日期和时间格式字符串,显示由当前日期和时间值表示的小时。 请注意,如果使用空格,它将在结果字符串中显示为文字字符。

那么, formats数组中的第一个元素中应该是% H吗?

希望这会有所帮助,最好的问候,汤姆。

我可能是错的,但我怀疑它可能与格式字符串的“H”部分固有的模糊性有关 – 即,给定字符串“123”,你可以处理小时“1”(01: 00)或小时“12”(12:00); 由于TryParseExact不知道哪个是正确的,因此返回false。

至于为什么这个方法没有提供“最佳猜测”:我担心文档不在你这边。 从DateTime.TryParse上的MSDN文档 (强调我的):

当此方法返回时,如果转换成功,则包含等效于s中包含的日期和时间的DateTime值;如果转换失败 ,则包含DateTime.MinValue 。 如果sformat参数为null ,为空字符串,或者不包含与format中指定的模式对应的日期和时间,则转换将失败。 此参数未初始化传递。

对于TryParseExact方法,“123”和“12345”似乎不明确。 例如,“12345”可以是12:34:50或01:23:45。 只是一个猜测。