This issue stems from an accounting package that spits out text-based reports with rows of data having invalid dates, like February 31st or September 31st.
The reports are formatted with spaces and mono-spaced fonts. My goal is to parse out the data needed and generate a more formal report (SSRS).
What I am interested in fixing is the situation where a date is invalid and can’t be directly converted into a DateTime struct. The date format from the report is MMM-dd-yy (e.g. Feb-30-10). I would like to convert the invalid date strings into the closest valid DateTime in the same month before showing them in the formal report. I’ve seen this done two ways in my time as a developer, both very poorly, so I want to come up with a simple way of doing it (if there isn’t a built-in way I don’t know about).
The first bad method I’ve seen(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 me a sad developer.
I’ve been trying to think of a more efficient way of doing this. Any ideas?
EDIT:
I found a solution and have posted it, but I liked Guffa’s answer more.
Reading the previous code, the last code is pretty much what I was going to suggest.
Here is a variation of the code: