C# .NET:为什么TryParseExact在Hmm和HMMS上失败?

C# .NET:为什么TryParseExact在Hmm和HMMS上失败?,c#,.net,datetime,parsing,datetime-format,C#,.net,Datetime,Parsing,Datetime Format,我正在尝试DateTime.TryParseExact方法,我遇到了一个我不懂的案例。我有一些格式和主题需要解析,每种格式都应该与其中一种格式完美匹配: var formats = new[] { "%H", "HH", "Hmm", "HHmm", "Hmmss", "HHmmss", }; var subjects = new[] {

我正在尝试
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天内接受它,除非有人提出更好的。谢谢你的帮助

0123 012345


我猜当它找到一个像这样的数字串时,它的长度应该是2/4/6。123应该是上午还是下午?0123并不是那样模棱两可。

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

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

至于为什么这个方法不能提供“最佳猜测”:恐怕文档不在你这一方。从(我的)重点:

当此方法返回时,包含
DateTime
相当于日期的值 和包含在s中的时间,如果 转换成功,
DateTime.MinValue
如果 转换失败
。转化 如果是s或格式,则失败 参数为
null
、为空字符串或不为空 包含一个日期和时间 对应于中指定的模式 格式。此参数已传递 未初始化


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

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

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

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

希望这有帮助, 顺致敬意, 汤姆

如果不使用日期或时间 自定义格式模式中的分隔符, 将不变区域性用于 提供程序参数和最宽的形式 每个自定义格式说明符的。对于 例如,如果要指定小时数 在阵列中,指定较宽的 形式为“HH”,而不是较窄的 表格“H”

引用:


正如其他人所指出的,H是不明确的,因为它意味着一天10小时,其中HH是12,所以我想我现在已经明白了这一切,多亏了更多的阅读、实验和其他有用的答案。所发生的事情是,H、m和s实际上在可能的情况下抓取了两个数字,即使格式的其余部分没有足够的数字。例如,使用Hmm格式和数字123,H将抓取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

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

是的,我也考虑过这一点,但in仍然不应该失败,是吗?我认为,一般认为,如果这类方法(接受
out
参数,返回bool)返回false,您不应该使用分配给
out
参数的内容。所以,一旦这个方法意识到它会失败,它就放弃了,不用费心去做“最佳猜测”。(当然,这只是我在大声思考…)很显然。但这里的重点不是我是否应该使用结果,而是为什么它首先没有给我一个;-)可以这样想:对于
DateTime
来说,这可能看起来很简单,但一般来说,将字符串解析为给定的数据类型需要一些工作。与其在结果没有任何用处的情况下这样做,为什么不退出并通知您的来电者您不能这样做呢?因为规范说我可以:p这是我们软件中的一项特殊功能,允许用户更快地键入日期和时间。我有一个类似的日期函数,例如,如果没有足够的数字来提取日期,则使用当前的月份和/或年份。在我看来,当格式是Hmm,字符串是123时,就不会有太多的歧义了。虽然它可能是,它需要12小时,然后无法匹配3到m。。。但你们