I am trying to sort date field in string format with invalid/null values. However, I am not getting the expected result.
var dataList = new List<string>();
dataList.Add("12/01/2020");
dataList.Add("12/01/2021");
dataList.Add("11/09/2022");
dataList.Add("01/31/2022");
dataList.Add("99999999");
dataList.Add(null);
var result = dataList.OrderByDescending(x =>
DateTime.TryParseExact(x, "MM/dd/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime endDate))
.ThenByDescending(x => x)
.ToList();
I am expecting 11/09/2022 to appear first. But, 12/01/2021 is appearing first instead. Any suggestion to fix this will be greatly appreciated.
CodePudding user response:
You order by the strings, not the datetimes. "12" is coming after "11". The rest of the string (and hence month and year) isn't compared anymore after the difference in the second character is found. Order your list by the datetimes:
var result = dataList
.OrderByDescending(x => DateTime.TryParseExact(x, "MM/dd/yyyy", System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime endDate) ? endDate : default(DateTime?))
.ToList();
Online demo: https://dotnetfiddle.net/G9VvXH
CodePudding user response:
The original code parse the date but throw the result away, then sort by the string instead. This will sort by putting valid datetime first, then sort by DateTime if it is valid, and the string value if it is not valid. Noted that for invalid date it does not make sense to sort by string, but at least this is deterministic e.g. it does not sort invalid string randomly.
var result = dataList
.Select(x => new {
dateString = x,
valid = DateTime.TryParseExact(x, "MM/dd/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime end),
endDate = end,
})
.OrderBy(x => x.valid ? 0 : 1)
.ThenByDescending(x => x.endDate)
.ThenByDescending(x => x.dateString)
.Select(x => x.dateString)
.ToList();
