Nella documentazione , si afferma esplicitamente che gli unici formati sicuri sono quelli che ho dimostrato all'inizio della domanda:
yyyyMMdd -- unseparated, date only
yyyy-MM-ddThh:mm:ss.fff -- date dash separated, date/time separated by T
Tuttavia, recentemente è stato portato alla mia attenzione che esiste un terzo formato che è ugualmente immune da qualsiasi lingua o impostazione del formato della data:
yyyyMMdd hh:mm:ss.fff -- unseparated date, no T separator
TL; DR: questo è vero. Per datetime
e smalldatetime
.
Continua a leggere per la versione più lunga e circa tutte le prove che otterrai.
C'è una scappatoia che spiega questo - mentre il corpo del testo principale non riesce a riconoscere yyyyMMdd hh:...
come un formato sicuro dalla lingua trasposta o dalle interpretazioni del formato della data, c'è un po 'di confusione che dice che la parte della data di tale stringa non è convalidata a seconda delle impostazioni del formato della data:
È piuttosto diverso da me prendere la documentazione alla sua parola, di solito. Puoi dire che sono un po 'scettico. E anche qui il linguaggio è ambiguo - afferma semplicemente che si tratta della combinazione di data e ora, non di chiamare esplicitamente lo spazio (che potrebbe essere un ritorno a capo, per quanto ne so). Dice anche che non è multi-lingua, il che significa che potrebbe fallire in alcune lingue, ma scopriremo tra poco anche che non è corretto.
Quindi ho deciso di dimostrare che nessuna combinazione di lingua / formato della data poteva far fallire questo formato specifico.
Innanzitutto, ho creato un piccolo blocco di SQL dinamico per ogni lingua:
EXEC sys.sp_executesql @sql, N'@lang sysname', N'us_english';
Ciò ha prodotto 34 righe di output in questo modo:
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)';
Ho copiato quell'output in una nuova finestra di query e, al di sopra di esso, ho generato questo codice, che si spera proverebbe a convertire quella stessa data (13 marzo) al 3 ° giorno del 13 ° mese in almeno un caso:
DECLARE @sql nvarchar(max) = N'
SET LANGUAGE @lang;
SET DATEFORMAT ydm;
SELECT @@LANGUAGE, CONVERT(datetime, ''20170313 23:22:21.020'');';
No, tutte le lingue lavorate sono semplicemente disponibili ydm
. Ho provato anche ogni altro formato e anche ogni tipo di dati data / ora. 34 conversioni di successo al 13 marzo, ogni volta.
Quindi, concedo a @AndriyM e @ErikE che, in effetti, esiste un terzo formato sicuro. Lo terrò a mente per i post futuri, ma ho battuto la batteria sugli altri due in così tanti posti, non li darò la caccia tutti e li correggerò ora.
Per estensione, penseresti che questo sarebbe sicuro, ma no:
yyyyMMddThh:mm:ss.fff -- unseparated date, T separator
Penso che in ogni lingua, questo produrrà l'equivalente di:
Messaggio 241, livello 16, stato 1, riga 8
Conversione non riuscita durante la conversione di data e / o ora dalla stringa di caratteri.
Per completezza, c'è un quarto formato di sicuro, ma è sicuro solo per le conversioni ai tipi data / ora più recenti ( date
, datetime2
, datetimeoffset
). In questi casi le impostazioni della lingua non possono interferire:
yyyy-MM-dd hh:mm:...
Tuttavia, consiglio vivamente di non utilizzarlo perché funziona solo per i tipi più recenti, e quelli vecchi sono ancora in una grande quantità di utilizzo, nella mia esperienza. Perché avere i trattini lì quando altrove (o di fatto nello stesso codice, se il tipo di dati cambia) devi rimuoverli?
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);
Anche con la stessa stringa di origine, le conversioni hanno prodotto risultati abbastanza diversi:
März Juli März
Il formato che funziona per datetime ( yyyyMMdd
) funzionerà sempre anche per la data e gli altri nuovi tipi. Quindi, IMHO, usalo sempre. E dato il terzo formato per i tipi con data / ora ( yyyyMMdd hh:...
), questo ti permetterà in realtà di essere più coerente, anche se il componente data è sempre un po 'meno leggibile.
Adesso mi ci vorranno solo alcuni anni, dare o prendere, per prendere l'abitudine di dimostrare i tre formati sicuri quando parlo della rappresentazione di stringhe di date.