views:

263

answers:

5

hey guys

I have a legacy application where the input is a date string, i.e.:

06/12/2009

The format of the input is always a string, and is consistent, it's always dd/mm/yyyy

At the moment the legacy app just INSERTS this in a DateTime fields. Obviously if the Localization Culture settings of the Server change, we have a bug.

Two questions:

One:

Whats the safest way to store Dates in SQLServer in this situation?

Is there a format that will always be correctly interpreted regardless of the order of day and month?

Two:

What settings exactly determines the culture of a SQLServer DB, is it an OS setting, or a setting of that DB, or what?

cheers

+6  A: 

Format YYYY-MM-DD is unambiguous, meaning that SQL Server won't confuse the month and day when converting a string value to DATETIME. (I've never experienced a problem with an implicit conversion using that format using the four digit year.)

The "safest" (and most convenient) way to store date values in SQL Server is to use DATETIME datatype.

Use the CONVERT function to explicitly specify the input and output formats when converting between DATETIME and strings.

SQL Server 2005 Documentation on CONVERT style argument values:

http://msdn.microsoft.com/en-us/library/ms187928(SQL.90).aspx

To convert a string representation to DATETIME datatype:

select CONVERT(datetime, '2009-06-03', 20)

The first argument is datatype to convert to, the second argument is the expression to be converted, the third argument is the style.

(style 20 is ODBC Canonical format = 'YYYY-MM-DD HH:MI:SS' (24 hour clock)


[FOLLOWUP]

To convert a DATETIME expression (e.g. getdate() to VARCHAR in 'YYYY-MM-DD' format:

select CONVERT(varchar(10), getdate(), 20)

Note that specifying varchar(10) gets you just the first 10 characters of the etnire 'YYYY-MM-DD HH:MM:SS' format.

[/FOLLOWUP]


As to what determines the default formats, that's going to be research. We avoid the issues caused by default formats by specifying the formats.

spencer7593
hey Spencer, thanks for the info. When doing a SELECT on the datetime field, how do I convert it back to a string in the universal format (yyyy-mm-dd)?
andy
@andy: answer updated to answer follow-up question. (I apologize for the incompleteness of the answer... I'm just giving you the SQL expressions to do the conversions. (I don't really have a good answer about everything that influences the default formats for regional/locale. (I'm an IT guy, I like my date strings canonical CCYYMMDDH24HMISS so I can sort them. Any format that doesn't have century and year leading, and I'm using three letter abbreviation for the month e.g. 03-JUN-2009. It AVOIDS AMBIGUITY.
spencer7593
Format YYYY-MM-DD is the ISO-8601 recommendation and will ALWAYS work on SQL Server regardless of your dateformat or language system settings. USE IT! :-) You can always convert from that universal format to whatever localized representation you need.
marc_s
@spencer: haha, yeah no need to apologize, thanks for your help. Just got back from fixing the legacy app....the handling of dates was pretty dismal, as was the code...
andy
+3  A: 

I would recommend storing all dates in UTC time when they are placed into the database. It will be consistent that way.

Storing dates like this seems to work well...

YYYY-MM-DD
RSolberg
ISO-8601 standard - works ALWAYS - why doesn't everyone use that already? :-)
marc_s
+3  A: 

See SET DATEFORMAT. The SQL 'culture' is set by SET LANGUAGE at a session level. SQL Server has its own date format settings, independent of the hosting OS. This is for several reasons: ANSI compliance, to prevent OS changes from affecting applications using the database hosted on that host and not least is compatibility, the SQL long predates the OS is currently running on.

Remus Rusanu
A: 

I'm a bit conservative in these matters, but I prefer to use separate Year / Month / Day fields in the table, rather than a Date field that uses a DBMS-specific data type. It certainly takes more space, but the lack of ambiguity and increased portability is worth it to me.

The price you pay is that you don't get free date/time arithmetic and sorting, but it's easy enough to do yourself or by a slightly more complex "ORDER BY" clause.

Drew Hall
Dates in ISO_8601 format (YYYY-MM-DD) will *ALWAYS* work on SQL Server - no matter how screwed up your date format or language settings are. No need for separating day, month, year into separate fields, really.
marc_s
@Marc: I'm sure you're right. For me the problem has always been at the interface between code and the DBMS--I can pull an integer out of any database, but date types are fickle and inconsistent between DB APIs, programming languages, etc.. It's just easier for me to treat things as ints when they reasonably can be. Personal choice, obviously...
Drew Hall
+2  A: 

Keep in mind that DATA is not its PRESENTATION. In this case that DATA is a DATE or DATETIME, regardless of how you show them.
As for inserting/updating/comparing datetime values, I quote the BOL:

When specifying dates in comparisons or for input to INSERT or UPDATE statements, use constants that are interpreted the same for all language settings: ADO, OLE DB, and ODBC applications should use the ODBC timestamp, date, and time escape clauses of:
{ ts 'yyyy-mm-dd hh:mm:ss[.fff] '} such as: { ts '1998-09-24 10:02:20' }
{ d 'yyyy-mm-dd'} such as: { d '1998-09-24' }
{ t 'hh:mm:ss'} such as: { t '10:02:20'}

I can assure you that, if you use this formats they will always work, regardless of the locale of you server

Turro