在文档中,非常明确地指出,唯一安全的格式是我在问题一开始就演示的格式:
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)';
我将该输出复制到一个新的查询窗口,并在其上方生成了以下代码,该代码有望在至少一种情况下尝试将同一日期(3月13日)转换为第13个月的第3天:
DECLARE @sql nvarchar(max) = N'
SET LANGUAGE @lang;
SET DATEFORMAT ydm;
SELECT @@LANGUAGE, CONVERT(datetime, ''20170313 23:22:21.020'');';
不,每种语言都可以在中找到ydm
。我也尝试了所有其他格式,也尝试了每种日期/时间数据类型。到3月13日,每次都有34次成功转换。
因此,我同意@AndriyM和@ErikE的确存在第三种安全格式。在以后的帖子中,我会牢记这一点,但是我在很多地方都在敲打其他两个架子,我现在不打算全力以赴地纠正它们。
通过扩展,您会认为这是安全的,但不能:
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
对于日期时间(作品格式yyyyMMdd
)将也始终日期和其他新类型的工作。因此,恕我直言,请始终使用它。给定日期/时间(yyyyMMdd hh:...
)类型的第三种格式,这实际上将使您更加一致-即使日期部分的可读性始终较低。
现在,我要花几年的时间来养成在谈论日期的字符串表示形式时演示三种安全格式的习惯。