user4146732
user4146732

Reputation:

Sort a list of dates using C#

I got a list of entries with a date, a text and a finished attribute.

I want to sort this list by the date. The date has the following format: dd.mm.yyyy

If I run this code, the result is mixed up like nothing happened. What's wrong?

this is my code:

// in the namespace
struct entry
{
    public string date;
    public string text;
    public bool finished;

    public entry(string _date, string _text, bool _finished)
    {
        date = _date;
        text = _text;
        finished = _finished;
    }
}

// in my class
List<entry> entrys = new List<entry>();

// ** fill the list with content **

// where i want to sort the list
entrys.Sort(delegate (entry x, entry y)
{
    string date1 = x.date;
    string date2 = y.date;

    // 0123456789
    // dd.mm.yyyy

    int day1 = Convert.ToInt32(date1.Substring(0, 2));
    int day2 = Convert.ToInt32(date2.Substring(0, 2));

    int month1 = Convert.ToInt32(date1.Substring(3, 2));
    int month2 = Convert.ToInt32(date2.Substring(3, 2));

    int year1 = Convert.ToInt32(date1.Substring(6, 4));
    int year2 = Convert.ToInt32(date2.Substring(6, 4));

    if (year1 > year2) return -1;
    if (month1 > month2) return -1;
    if (day1 > day2) return -1;

    return 1;
});

Upvotes: 0

Views: 3572

Answers (6)

Joel Coehoorn
Joel Coehoorn

Reputation: 416131

You're really doing this the hard way:

var entries = new List<entry>();
// ** fill the list with content **

entries = entries.OrderBy(e => DateTime.ParseExact(e.date, "dd.MM.yyyy", null)).ToList();

And one wonders why you don't already have .date property as a DateTime type instead of a string.

Upvotes: 2

Amit
Amit

Reputation: 26316

Just typed this quickly in LinqPad, the idea is to use Linq OrdeBy and defining a get property on the struct/class to return parsed DateTime. You can use TryPraseExact for additional safety.

void Main()
{
var list = new List<Entity>{
    new Entity{TempDate = "25.10.2015", SomeData="data1"},
    new Entity{TempDate = "20.10.2015", SomeData="data2"},
    new Entity{TempDate = "26.10.2015", SomeData="data3"},
    new Entity{TempDate = "18.10.2015", SomeData="data4"}};

list.Dump("Original");

list.OrderBy(x => x.DateTimeParsed).Dump("Sorted");
}

public struct Entity
{
public string TempDate {get; set;}
public DateTime DateTimeParsed{ get{ return DateTime.ParseExact(TempDate, "dd.mm.yyyy",CultureInfo.InvariantCulture); }}

public string SomeData {get; set;}
}

It is also a good idea to pass around DateTimeOffset instead of a string date

Upvotes: 0

Benison Sam
Benison Sam

Reputation: 2825

Always follow the KISS (Keep It Simple Stupid) principle:

entrys.Sort(delegate (entry x, entry y)
{
    DateTime dt1 = DateTime.ParseExact(x.date, "dd.MM.yyyy", 
          CultureInfo.InvariantCulture);
    DateTime dt2 = DateTime.ParseExact(y.date, "dd.MM.yyyy", 
          CultureInfo.InvariantCulture);

    return DateTime.Compare(dt1, dt2);
});

Upvotes: 0

Eldarien
Eldarien

Reputation: 813

No need to manually parse strings if computer can do that for you:

var provider = System.Globalization.CultureInfo.InvariantCulture;
entrys.Sort((a, b) => 
    DateTime.ParseExact(a.date, "dd.MM.yyyy", provider)
        .CompareTo(DateTime.ParseExact(b.date, "dd.MM.yyyy", provider)));

Upvotes: 0

Yacoub Massad
Yacoub Massad

Reputation: 27871

Your date field should become a DateTime. However, if for some reason you need it to be a string, then do the following:

First, add a GetDate method to your entry structure:

public DateTime GetDate()
{
    int day = Convert.ToInt32(date.Substring(0, 2));

    int month = Convert.ToInt32(date.Substring(3, 2));

    int year = Convert.ToInt32(date.Substring(6, 4));

    return new DateTime(year,month,day);
}

Then, use the following when you sort:

entrys.Sort((x, y) => x.GetDate().CompareTo(y.GetDate()));

Upvotes: 1

user4146732
user4146732

Reputation:

this code works:

entrys.Sort(delegate (entry x, entry y)
        {
            string date1 = x.date;
            string date2 = y.date;

            // 0123456789
            // dd.mm.yyyy

            int day1 = Convert.ToInt32(date1.Substring(0, 2));
            int day2 = Convert.ToInt32(date2.Substring(0, 2));

            int month1 = Convert.ToInt32(date1.Substring(3, 2));
            int month2 = Convert.ToInt32(date2.Substring(3, 2));

            int year1 = Convert.ToInt32(date1.Substring(6, 4));
            int year2 = Convert.ToInt32(date2.Substring(6, 4));

            if (year1 > year2) return 1;
            if (year1 == year2 && month1 > month2) return 1;
            if (year1 == year2 && month1 == month2 && day1 > day2) return 1;

            return -1;
        });

Upvotes: 0

Related Questions