views:

11

answers:

1

So there's this accounting package at my client that spits out text-based reports with invalid dates, like February 31st or September 31st.

The reports are formatted with spaces and mono-spaced fonts. The data that gets parsed out are fed into a more formal local SSRS report, and that's about all you need to know.

What I am interested in fixing is the situation where a date is invalid and can't be converted into a DateTime struct. The date format from the report is "MMM-dd-yy" (e.g. "Feb-30-10"). The date strings need to be fixed before being shown in the formal report. I've seen this done two ways in my time as a developer, and I want to come up with a cleverer way of doing it (if there isn't a built-in way I don't know about).

The first bad method (I can't believe I'm even showing you!):

Dim month As Integer = <Parse out the month from the bad date string>
Dim day As Integer = <Parse out the day from the bad date string>
Dim year As Integer = <Parse out the year from the bad date string>

Dim validDate As DateTime

While True
    Try
        validDate = New DateTime(year, month, day)
        Exit While
    Catch ex As ArgumentOutOfRangeException
        day -= 1
    End Try
End While

I hope I don't have to explain what I don't like about that method.

The second bad method:

Dim badDateString As String = <Current date string from text report>
Dim validDate As DateTime

If DateTime.TryParseExact(badDateString, "MMM-dd-yy", Nothing, Globalization.DateTimeStyles.None, validDate) Then
    Return validDate
End If

badDateString = badDateString.Replace("31", "30")

' ... try the parse again, if still not valid, replace "30" with "29"
' ... try the parse again, if still not valid, replace "29" with "28"

These make for some sad code and a sad developer.

I've been trying to think of a more efficient way of doing this. Any ideas?

EDIT:

Ah, geez. After two more seconds on the Internet I saw this and I can't believe I didn't think of the same solution earlier:

Dim validDate As DateTime
Dim dayMax As Integer = DateTime.DaysInMonth(year, month)
Dim newDay = day

If day > dayMax OrElse day < 1 Then
    newDay = dayMax
End If

validDate = new DateTime(year, month, newDay)

Return validDate

This is pretty simple and does exactly what I want. I guess I'll leave the question open though. Any other methods you've seen?

+1  A: 

Reading the previous code, the last code is pretty much what I was going to suggest.

Here is a variation of the code:

Return New DateTime(year, month, Math.Min(day, DateTime.DaysInMonth(year, month)))
Guffa