Reputation: 415
I have seen previous questions which are related my query but couldn't figure out on how to resolve my issue.
I have a list "Sites" with one of the items as "Year". It is defined as string and is in the format "MM/yyyy". When I try to sort the list based on the year, I'm facing a small problem.
Data for "Year" is
01/2012
04/2012
01/2013
06/2012
When I sort the list by using orderby, the output I'm getting is
01/2012
01/2013
04/2012
06/2012
which is incorrect.
Cannot convert the string using Convert.ToDateTime
as the string format doesn't contain day value. How should I go forward with this? How to implement DateTime.TryParseExact
without changing the format of the string?
Note : The format should be the same and the list should be sorted.
Upvotes: 5
Views: 2115
Reputation: 12805
You can still convert the string to a date within a LINQ statement, and the items will stay as strings.
var strings = new[]
{
"01/2012",
"04/2012",
"01/2013",
"06/2012"
};
var ordered = strings.OrderBy(s =>
{
var split = s.Split('/');
return new DateTime(int.Parse(split[1]), int.Parse(split[0]), 1);
});
Your last item will then be "01/2013"
.
As MethodMan showed in his answer, DateTime.Parse()
will be able to parse a MM/yyyy
formatted dated. However, if you need to perform anything that takes more than one line, this would be how you can do that. NB: This will not work in any query against a DbContext!
Upvotes: 4
Reputation: 3613
you also can create a new list with Dates converted to DateTime format and sort it after. It's a lot of lines but good for learning.
class Sites
{
public string Year { get; set; }
}
class MainClass
{
static void Main()
{
List<Sites> ListOfSites = new List<Sites>();
ListOfSites.Add(new Sites { Year = "01/2012" });
ListOfSites.Add(new Sites { Year = "04/2012" });
ListOfSites.Add(new Sites { Year = "01/2013" });
ListOfSites.Add(new Sites { Year = "06/2012" });
DateTime SiteYear;
List<DateTime> listWithDates = new List<DateTime>();
foreach (var item in ListOfSites)
{
if(DateTime.TryParse(item.Year, out SiteYear))
{
listWithDates.Add(SiteYear);
}
}
Display(SortAscending(listWithDates), "Sort Ascending");
}
static List<DateTime> SortAscending(List<DateTime> list)
{
list.Sort((a, b) => a.CompareTo(b));
return list;
}
static void Display(List<DateTime> list, string message)
{
Console.WriteLine(message);
foreach (var datetime in list)
{
Console.WriteLine(datetime);
}
Console.WriteLine();
}
}
Upvotes: -1
Reputation: 426
Implement System.IComparable interface:
public int CompareTo(object obj)
{
// Check null
if (obj == null)
return 1;
// Check types
if (this.GetType() != obj.GetType())
throw new ArgumentException("Cannot compare to different type.", "obj");
// Extract year and month
var year = int.Parse(this.Year.SubString(3, 4));
var month = int.Parse(this.Year.SubString(0, 2));
// Extract year and month to compare
var site = (Sites)obj;
var objyear = int.Parse(site.Year.SubString(3, 4));
var objmonth = int.Parse(site.Year.SubString(0, 2));
// Compare years first
if (year != objyear)
return year - objyear;
// Same year
// Compare months
return month - objmonth;
}
Upvotes: 0
Reputation: 18843
you could try something like this without having to change the input this will give you the order that you like also look at the OrderByDescending
property if you need it in a different sort order
var dateList = new List<string> { "01/2012", "04/2012", "01/2013", "06/2012" };
var orderedList = dateList.OrderBy(x => DateTime.Parse(x)).ToList();
Upvotes: 12