日期时间解析

31

我正在编写一个syslog服务器,用于接收syslog消息并将它们存储到数据库中。

我尝试将消息中接收的日期字符串解析为 DateTime 结构。

为了方便起见,在以下示例中,我将使用下划线代替空格;实际接收到的字符串有空格。

我接收到的字符串格式为"Jun__7_08:09:10" - 请注意月份和日期之间有两个空格。

如果日期在10号之后,则字符串变为"Jun_10_08:09:10"(一个空格)。

如果使用以下代码进行解析:

DateTime.ParseExact(Log.Date, "MMM  d HH:mm:ss", CultureInfo.InvariantCulture);

对于字符串的第1到第9个字符,它可以正常工作,但从第10个字符开始会抛出异常。如果我使用一个空格进行解析,则在第1到第9个字符上会抛出异常(并且从第10个字符开始可以正常工作)。

如何正确地解析这个字符串?


3
据我回忆,ParseExact 可以提供多个格式而不仅仅是一个。你可以尝试提供包括一位数字和两位数字格式的两种格式。但是可能存在一些格式,例如“MMM dd HH:mm:ss”(将空格替换为 d),但我不确定。 - Fendy
你使用 d 而不是 dd 有特定的原因吗? - user2244255
3
由于日期中的月份部分没有前导零,所以出现了这种情况。 - Rawling
当然,那是输入。算了,继续吧! - user2244255
5个回答

52

考虑使用这行代码:

DateTime.ParseExact(Log.Date,
    "MMM d HH:mm:ss",
    CultureInfo.InvariantCulture,
    DateTimeStyles.AllowWhiteSpaces);

请注意,我删除了月份和日期之间的一个空格。这是因为AllowWhiteSpaces字面意思是:

指定s可以包含格式未定义的前导、内部和尾随空格。


3
也许只需将AllowInnerWhite更具体化,但+1,直到现在我甚至不知道这些选项 :) - Rawling
3
+1 - 给我看一下DateTimeStyles,让我更仔细地研究一下它 :) - Oded
@Rawling,是的,“AllowInnerWhite” 在这里也可能很有效。 - Mike Perrenoud
@MichaelPerrenoud - 它确实可以(在LINQPad上测试过)。 - Oded
@Oded,非常感谢!你提醒我有多种格式可供选择!磨一块刃 - 这就是重点所在。你知道的,这就是我为什么喜欢体育精神徽章的原因,总有不止一种完成任务的方法。 - Mike Perrenoud
我不想修复这个问题,因为我不懂C#(而且据我所知,API可能有错别字),但是代码应该是AllowWhiteSpaces吧?(而不是Wite?) - Izkata

23

使用接受格式字符串数组的 DateTime.ParseExact 重载:

DateTime.ParseExact(Log.Date, 
                    new [] {"MMM  d HH:mm:ss", "MMM d HH:mm:ss"}, 
                    CultureInfo.InvariantCulture,
                    DateTimeStyles.None);

那个重载还需要一个 DateTimeStyles 参数。 - Tory
2
@Tory - 是的。你是指像我示例中的那个吗? - Oded
2
是的,就像你在评论时没有提到的那个一样。;P - Tory

3
您可以先删除额外的空格,然后解析该字符串:
DateTime.ParseExact(Log.Date.Replace("  ", " "), "MMM d HH:mm:ss", CultureInfo.InvariantCulture);

2
它并不美观而且相当缺乏灵活性,但它能胜任工作。 - levelnis

1

DateTime的ParseExact方法有一些重载,您可以传递多个格式,如果较早的格式无法使用,它们将被读取。这里是一个示例..

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string[] formats= {"M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt", 
                         "MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss", 
                         "M/d/yyyy hh:mm tt", "M/d/yyyy hh tt", 
                         "M/d/yyyy h:mm", "M/d/yyyy h:mm", 
                         "MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm"};
      string[] dateStrings = {"5/1/2009 6:32 PM", "05/01/2009 6:32:05 PM", 
                              "5/1/2009 6:32:00", "05/01/2009 06:32", 
                              "05/01/2009 06:32:00 PM", "05/01/2009 06:32:00"}; 
      DateTime dateValue;

      foreach (string dateString in dateStrings)
      {
         try {
            dateValue = DateTime.ParseExact(dateString, formats, 
                                            new CultureInfo("en-US"), 
                                            DateTimeStyles.None);
            Console.WriteLine("Converted '{0}' to {1}.", dateString, dateValue);
         }
         catch (FormatException) {
            Console.WriteLine("Unable to convert '{0}' to a date.", dateString);
         }                                               
      }
   }
}
// The example displays the following output:
//       Converted '5/1/2009 6:32 PM' to 5/1/2009 6:32:00 PM.
//       Converted '05/01/2009 6:32:05 PM' to 5/1/2009 6:32:05 PM.
//       Converted '5/1/2009 6:32:00' to 5/1/2009 6:32:00 AM.
//       Converted '05/01/2009 06:32' to 5/1/2009 6:32:00 AM.
//       Converted '05/01/2009 06:32:00 PM' to 5/1/2009 6:32:00 PM.
//       Converted '05/01/2009 06:32:00' to 5/1/2009 6:32:00 AM.

1
    DateTime.ParseExact(date, "MMM d HH:mm:ss", CultureInfo.InvariantCulture,DateTimeStyles.AllowInnerWhite)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接