views:

6239

answers:

6

I've written a stored procedure that takes in a date parameter. My concern is that there will be confusion between American and British date formats. What is the best way to ensure that there is no ambiguity between dates such as 02/12/2008. One possibility would be for users to enter a date in a format such as 20081202 (yyyymmdd). Is there any way to validate that without using sub strings? Alternatively dates could be entered as 02-Dec-2008(dd-mmm-yyyy), but again verification is not trivial and there are potential issues with users who do not use English.

Further to the first three answers . . . One issue is that I'm expecting this stored proc to be called directly without a front end so validation ouside of the proc is not an option. Is it a good idea to take the day, month and year as separate parameters?

+4  A: 

You won't have any problems whatsoever if you'd use parameters in your sproc:

create proc dbo.Sproc
    @date datetime
as
    ...
Anton Gogolev
We're already using the datetime type this issue is that depending on the user's localisation setting the same identical valid datetime inputs can have different meanings.
macleojw
So the question is not really about SQL, is it? You should just correctly parse input in your presentation layer and hand to SQL server a valid datetime.
Anton Gogolev
This proc will not have a presentation layer. That's why it's a SQL issue.
macleojw
+4  A: 

If you declare the parameter as being of type DATETIME or one of the other typed date/time types in SQL Server, which you should, then there is no ambiguity; it represents a particular date and time. The type of validation you're talking about should happen outside the stored procedure, not inside.


OK from your comments and edit, it appears the issue is with the way people call the SP rather than actually within it. To that end, you simply need to train your users to use sortable date format, i.e.

yyyy-MM-dd HH:mm:ss

And then there is no ambiguity. Anybody who is allowed near a database should be aware of localisation issues and should always be using a non-ambiguous format like this one when entering dates.

Greg Beech
There is ambiguity because the meaning of the date depends on localisation settings. E.g. 02/12/2008 is the 2nd of December to someone inthe UK but in the US it would be the 12th of February. Using a datetime format doesn't help as it is a valid date in both localisations.
macleojw
A DATETIME is not stored as a string, it is stored as a number of intervals since an epoch, therefore there is no ambiguity in the data type itself. A DATETIME is not a CHAR/VARCHAR by any means.
Greg Beech
You may be getting confused because it prints out differently depending on the locale? But that is only the way it is printed out. There is no ambiguity in the data a DATETIME actually contains.
Greg Beech
The ambiguity is in the input data which is entered as a string.
macleojw
A: 

If your proc accepts the date as a datetime parameter then there is little you can do to validate that the desired format is ddmmyyyy and not mmddyyyy. It all depends on how the user entered the date and how it was passed to SQL.

For example: On a web page i could add a parameter like this

command.Parameters.AddWithValue("@mydate",mydateVar.ToString("dd/MM/yyyy"));

OR

command.Parameters.AddWithValue("@mydate",mydateVar.ToString("MM/dd/yyyy"));

And SQL will just insert what its given as long as the string can be cast to a date correctly. It wont know the format you want to use so it will try to cast to its system default format.

A solution i use although it may not be applicable in your situation is to have users enter all dates in whatever frontend you have in the dd-MMM-yyyy format. I can then be sure of the format before i insert into the DB. I use that format everywhere to keep it all the same throughout the app.

Kaius
A: 

You said that you are expecting this stored proc to be called directly without a front end and validation ouside of the proc is not an option.

In that case the users will be inserting data directly, I also believe that in this case it is for internal use only (as the stored proc is going to be called directly)

So I think you have 2 options

  1. if you have disciplined users you can agree on one of the safe formats: ISO yyyyddmm, or ISO8601 yyyy-mm-dd Thh:mm:ss:mmm if you need a time part as well
  2. otherwise take 3 parameters: year, month, year and perform some validation inside the stored procedure
kristof
Thanks for your answer. Do you know of any way to check that a date has been input in one of the safe formats?
macleojw
Whatever checks you do you cannot be sure that when user enters 20090211 he means 11th of Feb or 2nd of Nov unless you clearly communicate the format. In your code your can assume that it is iso format and simply do the cast to datetime if that returns an error display the error message to the user
kristof
The safe format means that the SQL Server will always interpret the string as yyyyddmm when converting it to datetime type, no matter what are your locale settings
kristof
A: 

I say take a datetime and train them to use the ODBC canonical form of a date as in this example:

EXECUTE uspMyProc {d '2009-02-11'}

If you take a date that you have to parse, whether it be a string or the year, month and day as separate integer arguments, then you have to deal with days out of range for the month and year. Some functions that take those automatically advance or move backwards the day on you. Thus the trick of sending 0 for the day and getting the last day of the previous month. Others return an error. But handling that stuff yourself is probably not worth reinventing the wheel.

If you absolutely have to because novices will be running it directly (why would novices be running stored procedures directly?), I'd take three separate arguments and pass the concatenated date as a string in the format YYYY-MM-DD through ISDATE to verify the parameters and exit if it isn't valid.

Will Rickards
+1  A: 

I've ended up taking a string paramater for the date and require users to enter the month as a word. I check the input is a valid date by converting it to date. To ensure the month is entered as a word, I use the like comparator to compare the input string with "%Jan%" or "%Feb%" or "%Mar%" etc.

macleojw