hdoghmen
hdoghmen

Reputation: 3422

Parsing only dates in a list of string

Is it possible to check and parse only dates from this list :

List<string> everything = new List<string>
                   {"1", "A", "11/05/2013 22:43", "2.3", "21/11","null", "2012"};

This should return only parsed value of 11/05/2013 22:43.
Values 2.3 and 21/11 should not be returned.

Upvotes: 0

Views: 188

Answers (3)

Tim Schmelter
Tim Schmelter

Reputation: 460238

Use DateTimke.TryParse. You can use following LINQ query:

IEnumerable<DateTime> dates = everything
    .Select(str => str.TryGetDate(CultureInfo.InvariantCulture))
    .Where(d => d.HasValue)
    .Select(d => d.Value);

TryGetDate is following extension which is handy for LINQ queries:

public static DateTime? TryGetDate(this string item, params IFormatProvider[] formatProvider)
{
    if (formatProvider.Length == 0)
        formatProvider = new[]{ CultureInfo.CurrentCulture };
    bool success = false;
    DateTime d = DateTime.MinValue;
    foreach (var provider in formatProvider)
    {
        success = DateTime.TryParse(item, provider, DateTimeStyles.None, out d);
        if (success) break;
    }
    return success ? (DateTime?)d : (DateTime?)null;
}

Result:

Console.WriteLine(string.Join(", ", dates)); // 11/05/2013, 02/03/2013

Edit: since you want to parse exact use DateTime.TryParseExact. Here is another method that returns your desired result:

public static DateTime? TryGetDateExact(this string item, String[] allowedFormats = null, params IFormatProvider[] formatProvider)
{
    if (formatProvider.Length == 0)
        formatProvider = new[] { CultureInfo.CurrentCulture };
    if (allowedFormats == null || allowedFormats.Length == 0)
    {
        allowedFormats = formatProvider
        .Select(fp => { 
            DateTimeFormatInfo dti = DateTimeFormatInfo.GetInstance(fp); 
            return String.Format("{0} {1}", dti.ShortDatePattern, dti.ShortTimePattern);
        })
        .ToArray();
    }
    bool success = false;
    DateTime d = DateTime.MinValue;
    foreach (var provider in formatProvider)
    {
        success = DateTime.TryParseExact(item, allowedFormats, provider, DateTimeStyles.None, out d);
        if (success) break;
    }
    return success ? (DateTime?)d : (DateTime?)null;
}

You can use it in this way:

IEnumerable<DateTime> dates = everything
    .Select(str => str.TryGetDateExact(null, CultureInfo.InvariantCulture))
    .Where(d => d.HasValue)
    .Select(d => d.Value);

Note that i've used CultureInfo.InvariantCulture to force / as separator. You can omit all parameters if you want to use CultureInfo.CurrentCulture only with your format string.

Upvotes: 2

Jade
Jade

Reputation: 2992

This will ignore "2.3" as valid date value

        List<string> everything = new List<string> { "20131105", "1", "A", "11/05/2013 22:43", "2.3", "21/11", "null", "2012" };
        List<string> allDates = new List<string>();
        DateTime d;
        foreach (string s in everything)
        {
            if (s.Length < 8) continue;
            if (DateTime.TryParse(s, out d))
            {
                allDates.Add(s);
            }
        }

Upvotes: 0

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186813

You can use DateTime.TryParse: just try parsing every string in the list, and if parsing succeeded it's a DateTime

http://msdn.microsoft.com/en-us/library/ch92fbc1(v=vs.110).aspx

List<DateTime> datas = new List<DateTime>();

foreach (String st in everything) {
  DateTime dateTime;

  if (DateTime.TryParse(st, out dateTime)) // <- Probably you'll want to specify datetime formats here
    datas.Add(dateTime);
}

Upvotes: 1

Related Questions