У документації дуже чітко зазначено, що єдиними безпечними форматами є ті, які я продемонстрував на самому початку запитання:
yyyyMMdd -- unseparated, date only
yyyy-MM-ddThh:mm:ss.fff -- date dash separated, date/time separated by T
Однак нещодавно мені було донесено, що існує третій формат, який однаково захищений від будь-яких налаштувань мови чи дати:
yyyyMMdd hh:mm:ss.fff -- unseparated date, no T separator
TL; DR: Це правда. Для datetime
і smalldatetime
.
Читайте про довшу версію та про стільки доказів, скільки ви збираєтеся отримати.
Існує лазівка, яка пояснює це - хоча основний текст тексту не вдається визнати yyyyMMdd hh:...
формат, захищений від перекладеної мови чи інтерпретацій формату дати, є невелика розмитість, яка говорить про те, що частина дати такого рядка не перевірена залежно від налаштувань формату дати:
Зазвичай, я не схожу на те, щоб просто взяти документацію на слово. Можна сказати, що я трохи скептичний. І мова тут також неоднозначна - вона просто стверджує, що мова йде про поєднання дати та часу, а не чітко виклику місця (це може бути повернення вагона, наскільки я знаю). Він також говорить, що він не є багатомовним, що означає, що він може вийти з ладу на певних мовах, але незабаром ми з’ясуємо, що це також неправильно.
Тож я поклав на меті довести, що жодна комбінація мови / формату дати не може зробити цей конкретний формат невдалим.
По-перше, я створив невеликий блок динамічного SQL для кожної мови:
EXEC sys.sp_executesql @sql, N'@lang sysname', N'us_english';
Це дало 34 ряди вихідних даних так:
EXEC sys.sp_executesql @sql, N'@lang sysname', N'us_english';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Deutsch';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Français';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'日本語';
...
EXEC sys.sp_executesql @sql, N'@lang sysname', N'简体中文';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Arabic';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'ไทย';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'norsk (bokmål)';
Я скопіював цей вихід у нове вікно запитів, і над ним я сформував цей код, який, сподіваюся, спробував би перетворити ту саму дату (13 березня) на 3-й день 13-го місяця принаймні в одному випадку:
DECLARE @sql nvarchar(max) = N'
SET LANGUAGE @lang;
SET DATEFORMAT ydm;
SELECT @@LANGUAGE, CONVERT(datetime, ''20170313 23:22:21.020'');';
Ні, кожну мову працювали просто знайдіть ydm
. Я також пробував будь-який інший формат, а також кожен тип даних / дати. 34 успішні перетворення до 13 березня, кожного разу.
Отже, я погоджуюся @AndriyM та @ErikE, що, дійсно, існує 3-й безпечний формат. Я буду пам’ятати про це для майбутніх постів, але я забивав барабани про інші два у стільки місцях, я не збираюсь їх полювати і виправляти зараз.
З іншого боку, ви можете подумати, що це буде безпечно, але ні:
yyyyMMddThh:mm:ss.fff -- unseparated date, T separator
Я думаю, що в кожній мові це дасть еквівалент:
Повідомлення 241, рівень 16, стан 1, рядок 8
Перетворення не вдалося при перетворенні дати та / або часу з символьного рядка.
Для повноти картини , є четвертий безпечний формат, але це безпечно тільки для перетворення в більш нових типів дати / часу ( date
, datetime2
, datetimeoffset
). У цих випадках мовні налаштування не можуть перешкоджати:
yyyy-MM-dd hh:mm:...
Однак я дуже рекомендую не використовувати його, оскільки він працює лише для нових типів, а старі, як і раніше, знаходяться в значній кількості використання. Навіщо тире там, коли скрізь (або насправді в тому самому коді, якщо тип даних змінюється) ви повинні їх видалити?
SET LANGUAGE Deutsch;
DECLARE @dashes char(10) = '2017-03-07 03:34';
DECLARE @d date = @dashes, @dt datetime = @dashes, @dt2 datetime2 = @dashes;
SELECT DATENAME(MONTH,@d), DATENAME(MONTH,@dt), DATENAME(MONTH,@dt2);
Навіть даючи однаковий рядок джерела, конверсії дали зовсім інші результати:
März Juli März
Формат, який працює для datetime ( yyyyMMdd
), також завжди працюватиме для дати та інших нових типів. Отже, ІМХО, просто завжди використовуйте це. І з огляду на третій формат для типів з датою / часом ( yyyyMMdd hh:...
), це фактично дозволить вам бути більш послідовними - навіть якщо компонент дати завжди трохи читабельніший.
Тепер мені знадобиться лише кілька років, я хочу взяти, щоб я звик демонструвати три безпечні формати, коли я говорю про строкове представлення дат.