Есть ли способ найти первую строку, которая соответствует строке формата 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"
Теперь я могу найти эту строку, выполнив разбор, но мне интересно, есть ли поддержка библиотеки для этого?
Ответы
Ответ 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;
}