C# - Calculate min date / max date from a List
Asked Answered
D

6

11

I have a List which contains Dates :

List<string> StringDates;

    [0]: "04.03.2010"
    [1]: "09.03.2010"
    [2]: "11.03.2010"
    [3]: "12.03.2010"
    [4]: "16.03.2010"
    [5]: "18.03.2010"
    [6]: "19.03.2010"
    [7]: "23.03.2010"
    [8]: "25.03.2010"
    [9]: "26.03.2010"

Using C# what is the best/shortest way to find out min date / max date from this list ?

Dobbs answered 25/2, 2010 at 21:30 Comment(0)
F
19

I like the simple solution.

DateTime minDate = DateTime.MaxValue;
DateTime maxDate = DateTime.MinValue;
foreach (string dateString in StringDates)
{
    DateTime date = DateTime.Parse(dateString);
    if (date < minDate)
        minDate = date;
    if (date > maxDate)
        maxDate = date;
}
Firebox answered 25/2, 2010 at 21:39 Comment(6)
I actually started writing the same method, I don't think much could be done to beat O(n) time unless you put it into some type of heap structure that would let you solve it in O(logN) time but then you'd trade processor cycles which are amazingly cheap for double the memory storage which is less cheap comparatively.Ammon
@Jeffrey: Be careful of the globalization of the datetime format for the dates represented as strings!Mantra
@tommieb75 - Yes, I thought of that, but didn't include it, because I was being lazy. That part can be taken from Mark Byers's answer. I'll give him upvote for the ParseExact piece, and call it done. :-)Firebox
@Chris, you can't beat the O(n) time, because you have to read all the input to find out min and max values. I assume that in a real scenario the values are unsorted, because if not, this wouldn't make sense.Sassaby
@Sassaby true you would need to iterate through the whole list to add it to a different collection, so the only way to beat O(N) would be to start with some type of heap structure.Ammon
And for List<DateTime?> ?Pelting
A
30

Convert them to DateTime using ParseExact (or TryParseExact) and then use Linq to get the Min and Max:

List<DateTime> dates = StringDates
   .Select(x => DateTime.ParseExact(x, "dd.MM.yyyy", null))
   .ToList();
DateTime minDate = dates.Min();
DateTime maxDate = dates.Max();

Note that in your example the list was already sorted in ascending order. If you can guarantee that this will always be the case and you want better performance, you could just take the first and last element which would be O(1) instead of O(n). But the above is safer so even if your listed probably will always be sorted, you probably shouldn't make this optimization unless you actually need it, just in case one day the list doesn't come in sorted order.

Abbess answered 25/2, 2010 at 21:38 Comment(0)
C
22

use linq!:

    var list = new List<DateTime>();
    list.Add(new DateTime(2010, 1, 1));
    list.Add(new DateTime(2008, 1, 1));
    list.Add(new DateTime(2009, 1, 1));
    Console.WriteLine(list.Max(date => date));
    Console.WriteLine(list.Min(date => date));
Cellulose answered 25/2, 2010 at 21:36 Comment(0)
F
19

I like the simple solution.

DateTime minDate = DateTime.MaxValue;
DateTime maxDate = DateTime.MinValue;
foreach (string dateString in StringDates)
{
    DateTime date = DateTime.Parse(dateString);
    if (date < minDate)
        minDate = date;
    if (date > maxDate)
        maxDate = date;
}
Firebox answered 25/2, 2010 at 21:39 Comment(6)
I actually started writing the same method, I don't think much could be done to beat O(n) time unless you put it into some type of heap structure that would let you solve it in O(logN) time but then you'd trade processor cycles which are amazingly cheap for double the memory storage which is less cheap comparatively.Ammon
@Jeffrey: Be careful of the globalization of the datetime format for the dates represented as strings!Mantra
@tommieb75 - Yes, I thought of that, but didn't include it, because I was being lazy. That part can be taken from Mark Byers's answer. I'll give him upvote for the ParseExact piece, and call it done. :-)Firebox
@Chris, you can't beat the O(n) time, because you have to read all the input to find out min and max values. I assume that in a real scenario the values are unsorted, because if not, this wouldn't make sense.Sassaby
@Sassaby true you would need to iterate through the whole list to add it to a different collection, so the only way to beat O(N) would be to start with some type of heap structure.Ammon
And for List<DateTime?> ?Pelting
B
2

Via Linq, you can do:

from row in StringDates
group row by true into r 
select new { 
    min = r.Min(z => z), 
    max = r.Max(z => z) 
}
Boult answered 25/2, 2010 at 21:33 Comment(1)
The list is a List<string>. The min and max strings won't necessarily represent the min and max dates.Larkins
S
0

This is similar to @Jeffrey's answer, but instead of parsing each date, it first finds the min and max dates comparing its string values, and then it parses the values at the end.

// This method handles the date comparisons
private int WeirdComparer(string strDate1, string strDate2)
{
    int res = string.Compare(strDate1, 6, strDate2, 6, 4);
    if (res == 0)
        res = string.Compare(strDate1, 3, strDate2, 3, 2);
    if (res == 0)
        res = string.Compare(strDate1, 0, strDate2, 0, 2);
    return res;
}

public void FindMinAndMaxDates(IList<string> strDates, out DateTime minDate, out DateTime maxDate)
{
    string min = "99.99.9999";
    string max = "00.00.0000";
    foreach (string strDate in strDates)
    {
        if (WeirdComparer(strDate, min) < 0)
            min = strDate;
        if (WeirdComparer(strDate, max) > 0)
            max = strDate;
    }
    minDate = DateTime.ParseExact(min, "dd.MM.yyyy", null);
    maxDate = DateTime.ParseExact(max, "dd.MM.yyyy", null);
}
Sassaby answered 25/2, 2010 at 22:27 Comment(3)
This FindMinAndMaxDates has a IList<string> as input. How would you represent a null DateTime? As a null string? You'd just have to change the WeirdComparer to handle null dates, also use a consistent semantic of null dates comparison, and finally skip the ParseExact if the min/max date is null.Sassaby
Not use string, only using DateTime nullable typePelting
In that case you don't need the WeirdComparer function. You may easily get away using the default comparer for DateTime?. e.g if (Comparer<DateTime?>.Default.Compare(nullableDate, min) < 0).Sassaby
I
0

I know this isn't a direct answer to your question, but could help others if they come here looking for something similar.

I ran across this issue today while trying to find just the max date from a list of objects. Sometimes there won't be a value in the date for the objects so I had to figure out how to use a try parse with my linq.

From a combination of what Mark used here I came up with this to solve my problem

        List<string> stringDates = new List<string>();
        stringDates.Add("Not a date");
        stringDates.Add("2015-01-01");
        stringDates.Add("2015-10-10");
        stringDates.Add("2015-9-10");
        stringDates.Add("123");

        DateTime sapInvoiceDate;
        DateTime tempDate = DateTime.MinValue;
        sapInvoiceDate = stringDates.Select(x => DateTime.TryParse(x, out tempDate)).Select(x => tempDate).Max();  
Ial answered 27/8, 2015 at 15:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.