1
\$\begingroup\$

The way I've written this feels clunky. Particularly, it feels like I shouldn't need to have both a 'dateToCheck' and 'selectedDate' variables.

The objective is to find the Date in a list that is the closest to today (inclusive), with a preference for dates in the future.

The list is guaranteed to be passed in, in descending order.

The list can contain dates in the future...all the way to anytime in the past. Or just dates in the future. Or just today. Or just dates in the past. Anything...

Here is my working version:

Public Shared Function GetClosetDateToToday(lstOrderedDates As List(Of Date)) As Date

    ' Select the closest Delivery date to TODAY (inclusive) from the list of Ordered dates 
    If lstOrderedDates.Count > 1 Then
        Dim dateToCheck = lstOrderedDates.ElementAt(1)
        Dim selectedDate = lstOrderedDates.ElementAt(0)
        For i = 1 To lstOrderedDates.Count - 1

            If dateToCheck < Date.Now.Date Then
                Exit For
            End If

            If dateToCheck >= Date.Now.Date Then
                selectedDate = dateToCheck
            End If

            If i + 1 < lstOrderedDates.Count Then
                dateToCheck = lstOrderedDates.ElementAt(i + 1)
            End If
        Next i
        Return selectedDate
    ElseIf lstOrderedDates.Count = 1 Then
        Return lstOrderedDates.First()
    End If

    Return Nothing
End Function

Is there a better way?

\$\endgroup\$
1
\$\begingroup\$

Because this method is Public you should check if lstOrderedDates is Nothing and you should't believe that the passed List really is ordered.

Doing the check on lstOrderedDates.Count for 0 and 1 first will save one indentation for the meat of the code.

Placing Dim dateToCheck = lstOrderedDates.ElementAt(1) inside the loop will remove the need for the third if inside the loop.

The second if isn't needed at all because of the first if. You can just set selectedDate = dateToCheck.

Would lead to:

Public Shared Function GetClosetDateToToday(lstOrderedDates As List(Of Date)) As Date

    ' Select the closest Delivery date to TODAY (inclusive) from the list of Ordered dates 
    If lstOrderedDates is Nothing OrElse lstOrderedDates.Count = 0 Then
        Return Nothing 
    ElseIf lstOrderedDates.Count = 1
        Return lstOrderedDates.ElementAt(0) 
    End If
    Dim ordered as List(Of DateTime) = lstOrderedDates.OrderByDescending(function(d) d).ToList()
    Dim selectedDate = ordered.ElementAt(0)
    For i = 1 To ordered.Count - 1

        Dim dateToCheck = ordered.ElementAt(i)

        If dateToCheck < Date.Now.Date Then
            Exit For
        End If

        selectedDate = dateToCheck

    Next i
    Return selectedDate

End Function 

In C# I would do it using some Linq magic like so

    public static DateTime GetClosetDateToToday(List<DateTime> ordered)
    {
        if (ordered == null || ordered.Count == 0) { return default(DateTime); }

        var result = ordered
                     .OrderByDescending(item => item)
                     .LastOrDefault(item => item >= DateTime.Now);

        if (result == default(DateTime))
        {
            return ordered[0];
        }
        return result;
    }

which should be equal to the VB.NET version but without guarantee

Public Shared Function GetClosetDateToToday(lstOrderedDates As List(Of Date)) As Date

    ' Select the closest Delivery date to TODAY (inclusive) from the list of Ordered dates 
    If lstOrderedDates is Nothing OrElse lstOrderedDates.Count = 0 Then
        Return Nothing 
    End If

    Dim found as DateTime = lstOrderedDates
                            .OrderByDescending(function(d) d)
                            .LastOrDefault(function(d) d >= DateTime.Now)
    If found is Nothing then
        found = lstOrderedDates.ElementAt(0) 
    End If

    Return found 

End Function 
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.