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?