C# ParseExact/TryParseExact失败,时间为一位数

C# ParseExact/TryParseExact失败,时间为一位数,c#,datetime,C#,Datetime,我有一个没有字段分隔符的时间和日期值,我正试图使用TryParseExact将其解析为DateTime。时间组件有一个一位数的小时和两位数的分和秒 下面的表达: DateTime.ParseExact("20170101 84457", "yyyyMMdd Hmmss", System.Globalization.CultureInfo.InvariantCulture) 结果出现FormatException,消息为“字符串未被识别为有效的日期时间”。我假设这是因为时间不能被明确地

我有一个没有字段分隔符的时间和日期值,我正试图使用
TryParseExact
将其解析为
DateTime
。时间组件有一个一位数的小时和两位数的分和秒

下面的表达:

DateTime.ParseExact("20170101 84457", "yyyyMMdd Hmmss", 
    System.Globalization.CultureInfo.InvariantCulture)
结果出现
FormatException
,消息为“字符串未被识别为有效的日期时间”。我假设这是因为时间不能被明确地解决,但是由于
mm
ss
始终是两位数字,我不明白为什么这会是一个问题

以下是成功解析的结果:

  • 修改输入时间以包含分隔符(例如,“8:44:57”和“H:mm:ss”)
  • 如果小于6位,则将输入时间调整为前导零
这两个问题似乎都有点棘手。

根据:

如果format是不包含日期或时间分隔符(如“yyyyMMddHHmm”)的自定义格式模式,则为提供程序参数和每个自定义格式说明符的最宽形式使用不变区域性。例如,如果要在格式模式中指定小时,请指定较宽的形式“HH”,而不是较窄的形式“H”

因此,如果没有任何分隔符,则需要使用
HH
而不是
H

就我个人而言,我会将时间分量填充到6位,然后使用HH。以下对我来说很好:

DateTime.ParseExact("20170101 084457", "yyyyMMdd hhmmss", System.Globalization.CultureInfo.InvariantCulture);
如果要将其包装到自定义函数中,可以使用如下内容:

    static DateTime ParseDateTime(string input)
    {
        int dateInteger, timeInteger;

        var s = input.Split(' ');
        bool dateOK = int.TryParse(s[0], out dateInteger);
        bool timeOK = int.TryParse(s[1], out timeInteger);

        if (!dateOK || !timeOK) throw new FormatException("Invalid date/time string.");

        var newInput = String.Format("{0:00000000} {1:000000}", dateInteger, timeInteger);
        return DateTime.ParseExact(newInput, "yyyyMMdd hhmmss", System.Globalization.CultureInfo.InvariantCulture);
    }

从我的理解来看,解析尝试检索两个数字(如果可以的话),并从左到右进行解析


使用我的原始时间值
84857
和格式
Hmmss
的失败示例,因为小时后面跟一个数字,它将被解析为
84
——因此引发格式异常。

我也阅读并尝试了该操作。不幸的是,这表现出同样的行为。对我来说很好。你确定你答对了吗?我的回答是在你编辑答案,给时间加上前导零之前。我目前还在添加一个前导零,但这似乎有点混乱。如果输入中填充了前导的
0
(同样在您的示例中,您正在切换到12小时时钟而不是预期的24小时时钟),则仅使用
H
就可以了。我没有编辑我的答案以添加数字。。。我剪切并粘贴了Visual Studio中的工作代码。也许你看到的是另一个答案。FWIW,将时间存储为5位整数似乎也是一个难题,无意冒犯。这可能是一个黑客行为,但强制使用0前缀可能正是你必须要做的。原因似乎是ParseExact在引擎盖下如何工作,试图在可能的情况下贪婪地检索两个字符。这里有一个行为的崩溃:是的,这似乎是问题所在
DateTime.ParseExact
最终调用了
DateTimeParse.DoStritParse
,即使指定了
H
,它仍然会获取两位数字来计算小时数。如果您真的想看看它是如何工作的,源代码就在这里:格式H表示值可以在0到23之间。很明显,即使已将格式指定为H,值也可以是2位数字。也许是这样;It’这就是为什么要读2位数字来形成H。@nullPainter您也可以在我的答案中看到.NET团队对这种情况的建议。