Came across a curious problem. In our code the other day. I've come up with a quick fix, but I couldn't help wondering if there was a better way of doing it.

The problem comes when parsing the string values submitted via QueryString into typed objects that eventually end up in a SQL stored procedure. For most eventual comparison types, comparing strings is fine, but to do "less than" or "greater than" and the like with dates, the string has to be converted to a date first.

So we were doing this - value is submitted into the function as a string after being pulled out of the querystring:

Which worked fine for years, until someone tried to submit a three-part version number. Suddenly 1.3.1 became 2001-03-01 and the comparison stopped working.

My quick fix was just to check to see if there was more than one dot in the potential "date" and if so, leave it as a string. Easy. But the trouble is that while none of our clients currently use anything other than UTC date format, I got scared when I looked on Wikipedia and found how many countries use something like dd.mm.yy as a standard date format.

Is there a better way of telling an untyped version number from a date?

I think there is no general way to do this. Imagine valid dates, that also can be valid versions: 1.12.2012 or sth... Can be a Date, but also a Version of s.b. who increases Revision numbers with every build.
–
dognoseNov 14 '12 at 13:05

What are the input date formats you want to support (consider as valid input)? dd/MM/yyyy, MM/dd/yyyy, etc?
–
giacomelliNov 14 '12 at 13:05

1

Why are you worried about time and date formats that don't apply to your clients? If you use DateTime.ParseExact you are able to ignore any format that does not apply to your clients.
–
RamhoundNov 14 '12 at 13:13

2 Answers
2

There is no way that you can do this with just the date value alone. What you really need is another value indicating what the format of the DateTime in the querystring is.

Take for example your 1.3.1 format. Who is to say that it's not really able to be interpreted as January 3rd, 2011 (looking at it from left-to-right as opposed to right-to-left).

You have two options:

If you want a completely open value, you need a hint indicating how it should be interpreted (which you would use to adjust your call to set the options in the call to DateTime.TryParse), along with the caveat that if the hint is not provided, then the results may be indeterminable when the input is ambiguous

Reject anything that isn't in the expected format.

The first is preferable when dealing with user input, as you want to make it as easy as possible for your users and lower the bar to entry.

Note that if the user input is coming from say, a web page that uses HTML 5, you should be aware that the input tag allows for date and datetime input types. Not only does this have the benefit of allowing browsers to provide standardized (at least, across a platform) way of inputting this type of data, but it also provides for standardizing the format that data is transmitted in, meaning your input falls more into #2 than it does in #1.

The second is preferable when When dealing calls made from APIs, as the DateTime instances (or representations of them) can be modified to fit your expectations (since they have a strongly typed representation in memory already before calling your API).

Yes, I thought this was probably the answer. But I wanted to see if there was another solution. Thanks for confirming my suspicions.
–
Matt ThrowerNov 14 '12 at 13:24

@MattThrower Depending on what is submitting the query string, chances are you can lean towards 2), as HTML5 allows for input types of date and datetime. If you know your pages are in HTML5, then the format of your value is guaranteed every time, just like it would be if you had code providing values in the URL.
–
casperOne♦Nov 14 '12 at 13:26

Sadly the input isn't coming from a form - I should have made this clear. It's coming on the QueryString on a call to what's effectively a web service, so we have no way of sanitising it before it reaches our code.
–
Matt ThrowerNov 14 '12 at 13:55

@MattThrower If that's the case, then you should absolutely insist on rejecting the input if it doesn't match the exact format required; since it's machines talking to machines, it's easy to ensure and should be elevated to a complete halt when what you expect is not encountered (you're compromising yourself otherwise). In this case, using DateTime.TryParseExact with a specific format is the way to go. Anything else is a failure (this actually gives your clients some security as well, in the long run, as it indicates when their process is failing).
–
casperOne♦Nov 14 '12 at 13:57

Thanks for this. This was the first approach I tried but it still (obviously) limits the format to those we deem "acceptable". I wanted to see if there was something more open-ended to employ.
–
Matt ThrowerNov 14 '12 at 13:26