c# - todatetime - ¿Hay alguna forma de encontrar la primera cadena que coincida con una cadena de formato DateTime?
formato 24 horas c# (6)
Dada una cadena de formato de fecha y hora, ¿existe una manera estándar de encontrar la primera subcadena coincidente que coincida con ese formato?
por ejemplo, dado ...
d-MMM-yy H:mm:ss
y algún texto ...
"blah 1 2 3 7-Jul-13 6:15:00 4 5 6 blah"
Esperaría que volviera
"7-Jul-13 6:15:00"
Ahora puedo encontrar esta cadena haciendo un análisis, pero me pregunto si hay algún soporte de biblioteca para hacer esto.
No tengo conocimiento de nada que no sea DateTime.TryParse (o alternativamente, un RegEx) para hacer esto en .NET.
Configuraría un tokenizador de flujo, pasando solo pares de token candidatos a DateTime.TryParse (basado en una combinación de longitud mínima de cadena, una subserie tal vez verifica un par de guiones en el token 0 y un par de dos puntos en el token 1, etc.) Las verificaciones exactas dependerán de la cantidad de formatos de fecha / hora que esté soportando)
Podrías probar una expresión regular como:
^[0-9]+-[a-z A-z]+-[0-9]+/s[0-9]+:[0-9]+:[0-9]+
Puede que esta no sea la más eficiente, pero me pareció una pregunta interesante, así que pensé en probar este método.
Toma su cadena de formato DateTime y hace un patrón de cadena Regex a partir de la sustitución de cualquier letra con .
y espacios en blanco con //s
. Luego crea un objeto Regex a partir de ese patrón e intenta encontrar la primera coincidencia en la oración de entrada.
Esa coincidencia, si existe, se pasa luego a una llamada DateTime.TryParseExact
. Estoy seguro de que se pueden realizar mejoras, pero esto podría ayudar a dar una idea general sobre una técnica que no requiere la codificación de un Regex o el formato de la oración de entrada.
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");
}
}
Puedes probar 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;
}
}
Puedes probar esto:
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;
}
Tal vez algo como esto:
Encuentre cada parte de la cadena de formato analizando cada palabra en el texto y combine las 2 para crear el 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;
}
}
Probado
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"