Подтвердить что ты не робот

Есть ли способ найти первую строку, которая соответствует строке формата DateTime?

С учетом строки формата даты, существует ли стандартный способ найти первую подходящую подстроку, соответствующую этому формату?

например, учитывая...

d-MMM-yy H:mm:ss

и некоторый текст...

"blah 1 2 3 7-Jul-13 6:15:00 4 5 6 blah"

Я ожидаю, что он вернется

"7-Jul-13 6:15:00"

Теперь я могу найти эту строку, выполнив разбор, но мне интересно, есть ли поддержка библиотеки для этого?

4b9b3361

Ответ 1

Это может быть не самым эффективным, но это казалось интересным вопросом, поэтому я решил попробовать этот метод.

Он берет вашу строку формата DateTime и выдает шаблон строки Regex из нее, заменяя любые буквы . и whitespace на \\s. Затем он создает объект Regex из этого шаблона и пытается найти первое совпадение во входном предложении.

Это соответствие, если оно существует, затем передается в вызов DateTime.TryParseExact. Я уверен, что улучшения могут быть сделаны, но это может помочь дать общее представление о методе, который не требует жесткого кодирования Regex или формата входного предложения.

string inputSentence = "blah 1 2 3 7-Jul-13 6:15:00 4 5 6 blah";

string dtformat = "d-MMM-yy H:mm:ss";

//convert dtformat into regex pattern
StringBuilder sb = new StringBuilder();
foreach (char c in dtformat)
{
    if (Char.IsLetter(c))
    {
       if (char.ToUpperInvariant(c) == 'D' || char.ToUpperInvariant(c) == 'H' || char.ToUpperInvariant(c) == 'S')            
          sb.Append(".{1,2}");
       else
          sb.Append(".");
    }
    else if(Char.IsWhiteSpace(c))        
       sb.Append("\\s");
    else
       sb.Append(c);
}


string dtPattern = sb.ToString();

Regex dtrx = new Regex(dtPattern);

//get the match using the regex pattern
var dtMatch = dtrx.Match(inputSentence);

if(dtMatch != null)
{
    string firstString = dtMatch.Value.Trim();

    //try and parse the datetime from the string
    DateTime firstMatch;
    if (DateTime.TryParseExact(dstr, dtformat, null, DateTimeStyles.None, out firstMatch))
    {
       Console.WriteLine("Parsed");
    }
    else
    {
       Console.WriteLine("Could not parse");
    }
}

Ответ 2

Возможно, что-то вроде этого:

Найдите каждую часть строки формата, проанализировав каждое слово в тексте и соедините 2, чтобы создать DateTime

string test = "blah 1 2 3 7-Jul-13 6:15:00  4 5 6 blah";

int formatPart = 0;
bool dateFound = false;
string format = "d-MMM-yy H:mm:ss";
DateTime myDateTime = DateTime.MinValue;
foreach (var item in test.Split(' '))
{
    DateTime dummy;
    if (DateTime.TryParseExact(item, format.Split(' ')[formatPart], null, DateTimeStyles.NoCurrentDateDefault, out dummy))
    {
        if (myDateTime == DateTime.MinValue)
        {
            formatPart++;
            myDateTime = dummy;
            dateFound = myDateTime.Date != DateTime.MinValue.Date;
            continue;
        }

        // If date was found first, add time, else add date
        myDateTime = dateFound
         ? myDateTime.Add(new TimeSpan(dummy.Hour, dummy.Minute, dummy.Second))
         : dummy.Add(new TimeSpan(myDateTime.Hour, myDateTime.Minute, myDateTime.Second));
        break;
    }
}

Испытано:

Input: "blah 1 2 3 7-Jul-13 6:15:00  4 5 6 blah"
Format: "d-MMM-yy H:mm:ss"

Input: "blah 1 2 3 6:15:00 7-Jul-13 4 5 6 blah"
Format: "H:mm:ss d-MMM-yy"

Input: "blah 1 2 3 6:15:00 7-7-2013 4 5 6 blah"
Format: "H:mm:ss d-M-yyyy"

Input: "blah 1 2 3 07-07-2013 6:15:00  4 5 6 blah"
Format: "dd-MM-yyyy H:mm:ss" 

Ответ 3

Вы можете попробовать NodaTime:

var input = "blah 1 2 3 7-Jul-13 6:15:00 4 5 6 blah";
var pattern = "d-MMM-yy H:mm:ss";
var nodaPattern = NodaTime.Text
    .LocalDateTimePattern
    .Create(pattern, System.Globalization.CultureInfo.CurrentUICulture);
for (int i = 0; i < input.Length - pattern.Length; i++)
{
    var result = nodaPattern.Parse(input.Substring(i, pattern.Length));
    if (result.Success)
    {
        Console.WriteLine(result.Value);
        break;
    }
}

Ответ 4

Я не знаю ничего, кроме DateTime.TryParse(или, альтернативно, RegEx) для этого в .NET.

Я бы установил токенизатор потока, передавая только пары пар токенов в DateTime.TryParse(на основе некоторой комбинации минимальной длины строки, может быть, подстрока проверяет пару тире на токене 0 и пару двоеточий на токене 1 и т.д. Точные проверки будут зависеть от того, сколько форматов даты/времени вы поддерживаете)

Ответ 5

Вы можете попробовать регулярное выражение, например:

^[0-9]+-[a-z A-z]+-[0-9]+\s[0-9]+:[0-9]+:[0-9]+

Ответ 6

Вы можете попробовать следующее:

string original = "blah 1 2 3 7-jul-13 6:15:00 4 5 6 blah";
Match mc = Regex.Match(original, @"\s*(?<date>\d+[-/][A-Z]{3}[-/]\d+)\s*([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]", RegexOptions.IgnoreCase);

if (mc.Success)
{
    string datetime = mc.Groups[0].Value;
}