从字符串中提取日期时间并检查值

时间:2018-07-26 10:34:49

标签: c# regex datetime

好,提取日期的方法如下:

public DateTime ExtractDateTime(string log)
{
    var regex = new Regex(@"\d{4}.\d{2}.\d{2} \d{2}.\d{2}.\d{2}.\d{4}");
    var match = regex.Match(log);
    return match.Success ? DateTime.ParseExact(match.Value, "yyyy.MM.dd hh:mm:ss:ffff", CultureInfo.InvariantCulture) : new DateTime();
}

日志文件如下:

  

“ 2018.07.26 10:33:05:0927:ECOM-请求新会话...成功(启动开始会话线程)”,

我创建了一个测试,以确保提取的DateTime是正确的。测试方法如下:

[Test]
public void CanExtractDate()
{
    // Assemble
    var service = TroposContext.GivenServices();
    var log = service.WhenCreateLog("ECOM - New Session Requested... Success (Start Session Thread Started)", 2018, 7, 26, 10, 33, 5, 927, out var actualDate);

    // Act
    var dateTime = service.LogValidator.ExtractDateTime(log);
    var compare = dateTime.CompareTo(actualDate);

    // Assert
    compare.Should().Be(0);
}

它失败了,因为compare实际上是-1。 方法WhenCreateLog有一个out DateTime参数,该参数由发送给该方法的参数创建。该方法如下所示:

public string WhenCreateLog(string log, int year, int month, int day, int hour, int minute, int second, int millisecond, out DateTime actualDate)
{
    var request = $"{year}.{month.ToString().PadLeft(2, '0')}.{day.ToString().PadLeft(2, '0')} {hour.ToString().PadLeft(2, '0')}:{minute.ToString().PadLeft(2, '0')}:{second.ToString().PadLeft(2, '0')}:{millisecond.ToString().PadLeft(4, '0')}: {log}";
    actualDate = new DateTime(year, month, day, hour, minute, second, millisecond);
    return request;
}

因此,在检查两个日期时,我可以看到dateTime变量的毫秒数等于92,而actualDate为927。 actualDate是正确的,dateTime为什么显示不正确?

2 个答案:

答案 0 :(得分:0)

我已经弄清楚了。看来new DateTime()毫秒介于0到999之间。但是我的字符串使用的是4位数字。 DateTime.ParseExact允许我拥有任何价值,因此我必须确保两种方法都使用相同的ParseExact。因此,我将 LogValidator 方法更改为此:

public const string Format = "yyyy.MM.dd hh:mm:ss:ffff";
public DateTime ExtractDateTime(string log)
{
    var regex = new Regex(@"\d{4}.\d{2}.\d{2} \d{2}.\d{2}.\d{2}.\d{4}");
    var match = regex.Match(log);
    return match.Success ? DateTime.ParseExact(match.Value, Format, null) : new DateTime();
}

然后将我的 WhenCreateLog 方法更改为:

public string WhenCreateLog(string log, int year, int month, int day, int hour, int minute, int second, int millisecond, out DateTime actualDate)
{
    var dateString = $"{year}.{month.ToString().PadLeft(2, '0')}.{day.ToString().PadLeft(2, '0')} {hour.ToString().PadLeft(2, '0')}:{minute.ToString().PadLeft(2, '0')}:{second.ToString().PadLeft(2, '0')}:{millisecond.ToString().PadLeft(4, '0')}";
    var request = $"{dateString}: {log}";
    actualDate = DateTime.ParseExact(dateString, LogValidator.Format, null);
    return request;
}

那行得通

答案 1 :(得分:0)

好吧,如果您想保留这四个位置,您可以将毫秒PadLeft更改为PadRight,这没关系。另一种选择是使用DateTime.ToString()重载,只是更改语句的顺序:

选项1:

var dateString = $"{year}.{month.ToString().PadLeft(2, '0')}.{day.ToString().PadLeft(2, '0')} {hour.ToString().PadLeft(2, '0')}:{minute.ToString().PadLeft(2, '0')}:{second.ToString().PadLeft(2, '0')}:{millisecond.ToString().PadRight(4, '0')}";

选项2:

actualDate = new DateTime(year, month, day, hour, minute, second, millisecond);
var request = $"{actualDate.ToString("yyyy.MM.dd HH:mm:ss:ffff")}: {log}";

此外,您应该检查Date是否有效,并且最好使用静态Regex.Match而不是实例,因为静态方法会缓存模式以加快将来的使用:

public DateTime ExtractDateTime(string log)
{
    string pattern = @"\d{4}.\d{2}.\d{2} \d{2}.\d{2}.\d{2}.\d{4}";
    var match = Regex.Match(log, pattern);
    DateTime parsedDate;
    if(DateTime.TryParseExact(match.Value, "yyyy.MM.dd hh:mm:ss:ffff",System.Globalization.CultureInfo.InvariantCulture,System.Globalization.DateTimeStyles.None, out parsedDate))
    {
        return parsedDate;
    }
    return new DateTime();
}

public string WhenCreateLog(string log, int year, int month, int day, int hour, int minute, int second, int millisecond, out DateTime actualDate)
{
    actualDate = new DateTime(year, month, day, hour, minute, second, millisecond);
    var request = $"{actualDate.ToString("yyyy.MM.dd HH:mm:ss:ffff")}: {log}";
    //Or
    //var request = $"{year}.{month.ToString().PadLeft(2, '0')}.{day.ToString().PadLeft(2, '0')} {hour.ToString().PadLeft(2, '0')}:{minute.ToString().PadLeft(2, '0')}:{second.ToString().PadLeft(2, '0')}:{millisecond.ToString().PadRight(4, '0')}";
    return request;
}