【问题标题】:C# DateTime.Parse efficiently time with hour/min/sec/milis/micro/nano secondsC# DateTime.Parse 以小时/分钟/秒/毫秒/微/纳秒有效地计时
【发布时间】:2018-11-13 11:57:51
【问题描述】:

我从第三方获得了我想转换为 DateTime 的字符串: “2018 年 11 月 13 日 16:08:52:000:000:000” 我已经尝试了这些选项,但 FormatException 被抛出:

System.DateTime.ParseExact("12 NOV 2018 16:08:52:000:000:000", 
                           "dd MMM yyyy HH:mm:ss:fff:ffffff:fffffffff", 
                                             CultureInfo.InvariantCulture)

当我使用这个时,同样的例外:

System.DateTime.ParseExact("12 NOV 2018 16:08:52:000:000:000",
                            "dd MMM yyyy HH:mm:ss:fff", CultureInfo.InvariantCulture)

是否有一种干净的方法可以按原样解析它,或者我需要使用像string.Split(new []{':'}) 这样的脏方法?

注意:

  • 对于我的业务需求,我不需要微/纳秒的部分。
  • 由于这种解析操作在一秒钟内发生多次,因此效率是关键因素。

更新

我选择了@Tim 的建议来进行字符串操作:

string date = "12 NOV 2018 16:08:52:000:000:000";
date = date.Remove(date.Remove(date.LastIndexOf(':')).LastIndexOf(':'));
DateTime result = System.DateTime.ParseExact(date, "dd MMM yyyy HH:mm:ss:fff", System.Globalization.CultureInfo.InvariantCulture);

原因:

  • 我不能保证date 字符串的结构,因为它来自第三方。所以使用格式模式dd MMM yyyy HH:mm:ss:fff:fff:fff会很危险
  • 正如@Jeroen Mostert 所写,当您使用DateTime.ParseExact() 时,字符串拆分的使用并不是关键因素

另外,如果您真的认为效率如此重要,请不要假设对 DateTime.ParseExact 的任何一次调用都会“快速”,或者您所做的任何字符串拆分都会成为瓶颈。

【问题讨论】:

  • 微秒和纳秒总是为零吗?
  • 如果效率是一个关键因素,请考虑从根本上解决问题并让系统输出一种在任何地方都可以轻松解析的格式——比如绝对滴答声。我知道这些事情的答案通常是“不,我不能改变任何”,但话说回来,现实世界的问题是你拒绝应用有效解决方案时留下的问题,所以它总是值得的试。此外,如果您真的认为效率如此重要,请不要假设对 DateTime.ParseExact 的任何一次调用都会“快速”,或者您所做的任何字符串拆分都会成为瓶颈。
  • 仅供参考,我已编辑 my answer 以展示删除不必要部分的方法。
  • @themehio 因为它来自第三方,我不能保证微/纳米永远是零。

标签: c# datetime datetime-format


【解决方案1】:

嗯,不就是这样吗?

System.DateTime.ParseExact("12 NOV 2018 16:08:52:000:000:000", 
                           "dd MMM yyyy HH:mm:ss:fff:fff:fff", 
                           System.Globalization.CultureInfo.InvariantCulture)

如果f 的所有组具有相同的值,例如所有0123,则此方法有效。

Tbh,我不明白你为什么认为 fff:ffffff:fffffffff 匹配 000:000:000

对于我的业务需求,我不需要微/纳秒的部分。

您可以通过切断微/纳米部分来使您的第二种格式正常工作:

string date = "12 NOV 2018 16:08:52:000:000:000";
date = date.Remove(date.Remove(date.LastIndexOf(':')).LastIndexOf(':'));
DateTime result = System.DateTime.ParseExact(date, "dd MMM yyyy HH:mm:ss:fff", System.Globalization.CultureInfo.InvariantCulture);

当然,这假设总是至少有两个冒号。很明显,您需要try-catch 来记录无效值并继续下一个。

【讨论】:

  • 似乎三组 f 被处理为重复项,这意味着它只会解析以 :443:443:443 之类结尾的字符串,如果即使其中一组不同,它也会抱怨“DateTime 模式'f' 以不同的值出现不止一次。"
  • @LasseVågsætherKarlsen:是的,看起来是这样,又学到了一些新东西:)
  • 为什么不简单地.Substring(0, "dd MMM yyyy HH:mm:ss:fff".Length)?初始部分是固定的。
  • @JeroenMostert:格式可以包含special or formatting characters,如'。从末尾截断不必要的部分更安全。
  • 在这种情况下你会使用.Substring(0, "dd/MM/yyyy")。我看到了困惑:我只是使用格式字符串作为简写来避免长度的魔法常数,并清楚地说明我们对长度的了解来自哪里;我并不是建议在Substring 中始终按字面意思使用格式字符串。我想,无论是假设前缀长度还是假设“带冒号的最后两个部分总是可以安全地被切断”在面对变化时是稳健的,这是一个见仁见智的问题。这要么被测试覆盖,要么在没有覆盖时会很快失败。
【解决方案2】:

不是一个准确的答案

System.DateTime.ParseExact("25 NOV 2018 16:08:52:000:000:000",
                            "dd MMM yyyy HH:mm:ss:fff:fff:fff", CultureInfo.InvariantCulture);

要考虑的事项:输入字符串的计数(000)应与格式(fff)匹配,

000 = fff 好

00 = fff 不好

000 = ff 不好

您可能需要在尝试解析之前操作输入日期字符串。

有关使用格式说明符 (fff) 的更多信息,请参阅此处

https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings

.NET 小提琴:

https://dotnetfiddle.net/5UxCkd

【讨论】:

    【解决方案3】:

    我认为 :fff 具有相同的格式是这里的关键因素

    System.DateTime.ParseExact("12 NOV 2018 16:08:52:000:000:000","dd MMM yyyy H:mm:ss:fff:fff:fff", CultureInfo.InvariantCulture) 似乎有效

    https://dotnetfiddle.net/ZAtchu 示例代码

    【讨论】:

      猜你喜欢
      • 2013-01-12
      • 2012-06-08
      • 1970-01-01
      • 2018-11-16
      • 1970-01-01
      • 2012-02-12
      • 1970-01-01
      • 2019-08-01
      • 1970-01-01
      相关资源
      最近更新 更多