【问题标题】:ParseExact/TryParseExact failing with single digit hour [duplicate]ParseExact/TryParseExact 以个位数小时失败 [重复]
【发布时间】:2017-07-10 21:49:17
【问题描述】:

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

下面的表达式:

DateTime.ParseExact("20170101 84457", "yyyyMMdd Hmmss", 
    System.Globalization.CultureInfo.InvariantCulture)

导致FormatException 出现消息“字符串未被识别为有效的日期时间。”。我假设这是因为时间无法明确解决,但是由于 mmss 总是每个都是两位数,我不明白为什么这会是一个问题。

以下结果解析成功:

  • 破解输入时间以包含分隔符(例如,“8:44:57”和“H:mm:ss”)
  • 如果

这两个似乎都有些小技巧。

【问题讨论】:

  • 这可能是一个 hack,但强制使用 0 前缀可能就是你必须要做的。
  • 看来原因是 ParseExact 是如何在后台工作的,它试图在可能的情况下贪婪地检索两个字符。这里有行为的细分:stackoverflow.com/questions/2016206/…
  • 是的,这似乎是问题所在。 DateTime.ParseExact 最终调用 DateTimeParse.DoStrictParse,即使您指定 H,它仍然会抓取两位数来计算小时。如果你真的想看看它是如何工作的,源代码在这里:referencesource.microsoft.com/mscorlib/R/f1835935628e4a2f.html
  • 格式 H 表示值可以在 0 到 23 之间。很明显,即使格式已指定为 H,值仍然可以是 2 位数。也许这就是为什么要读取 2 位来形成 H 的原因。
  • @nullPainter 您也可以在我的回答中看到 .NET 团队针对这种情况提出的建议。 stackoverflow.com/a/26778076/447156

标签: c# datetime


【解决方案1】:

据我从other people's research 了解到,如果可以,解析尝试检索两位数,并从左到右解析。

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

【讨论】:

    【解决方案2】:

    根据the documentation

    如果 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);
        }
    

    【讨论】:

    • 我也阅读并尝试过。不幸的是,这表现出相同的行为。
    • 对我来说很好。你确定你没看错?
    • 我的回答是在您编辑它以在时间中添加前导零之前对您的回答做出回应。我目前也在添加前导零,但这似乎有点杂乱无章。
    • 如果输入用前导 0 填充,则仅使用 H 可以正常工作(在您的示例中,您正在切换到 12 小时制而不是预期的 24 小时制)
    • 我没有编辑答案来添加数字...我从我的 Visual Studio 剪切并粘贴了工作代码。也许您正在寻找不同的答案。 FWIW,将时间存储为 5 位整数也似乎是一个杂物,没有冒犯。
    猜你喜欢
    • 1970-01-01
    • 2012-12-02
    • 1970-01-01
    • 2011-01-02
    • 2020-03-08
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多