在T-SQL中将日期时间截断到秒(去除毫秒)

46

如何将包含毫秒的日期时间缩短为仅包含秒?

例如,将2012-01-25 17:24:05.784转换为2012-01-25 17:24:05


旁注:在我的情况下,我很有兴趣比较日期,但忽略微小的差异(以便找到模糊匹配记录)。 找到DATEDIFF(SECONDS ...)小于1的位置更有意义。 - bambams
9个回答

62

这将截断毫秒部分。

declare @X datetime
set @X = '2012-01-25 17:24:05.784'
select convert(datetime, convert(char(19), @X, 126))
或者
select dateadd(millisecond, -datepart(millisecond, @X), @X)

CAST和CONVERT
DATEADD
DATEPART


2
第二种解决方案,减去毫秒,非常简单而巧妙。 - David R Tribble

25

最快、同时也是语言安全和确定性最高的

DATEADD(second, DATEDIFF(second, '20000101', getdate()), '20000101')

1
我使用了2000来避免整数溢出。如果你想的话,你可以使用19700101。 - gbn
1
这确实非常快。问题是它返回了错误的结果。也许如果你用“second”替换“dd”,就可以解决问题。 - t-clausen.dk
@MikaelEriksson 不,尝试运行一百万次。这样会快两倍。 - t-clausen.dk
1
@t-clausen.dk:如有明显的笔误,请随意编辑我的答案 :-) - gbn
1
@t-clausen.dk - 在我的测试中没有。强制转换版本要慢三倍,而“dateadd”版本与我的版本类似,但我的版本稍微快一些。@gbn 这是给你的博客文章 :). 改掉的坏习惯 - Mikael Eriksson
显示剩余2条评论

13

现在最简单的方式是:

select convert(datetime2(0) , getdate())

1
对于那些稍后查看此答案的人...你可能会遇到问题。例如:SELECT CONVERT(DATETIME2(0), '2018-07-19 11:59:59.999') - hyphen
@hyphen 这个评论还有效吗?你的例子会产生2018-07-19 12:00:00,这在我看来是正确的结果。另外,午夜边缘情况也可以正常工作。即 SELECT CONVERT(DATETIME2(0), '2018-07-19 23:59:59.999' 将得到 2018-07-20 00:00:00。 - Tim
1
正如第一条评论所建议的那样,这个回答并不截断秒数,它会四舍五入。如果你需要截断秒数,请不要使用这个回答。 - Jamie F

9
convert(datetime, convert(varchar, @datetime_var, 120), 120)

1
稍微简洁一些的写法是:CAST(CONVERT(VARCHAR, @date, 120) AS DATETIME)。 - Brandon Hill

4
以下是非常快速的性能,但它不仅可以去掉毫秒,还可以四舍五入到分钟。请参见(http://msdn.microsoft.com/en-us/library/bb677243.aspx)
select cast(yourdate as smalldatetime) from yourtable

编辑:

以下脚本旨在比较Mikael和gbn的脚本,我都点赞了因为两个答案都很棒。测试结果表明,gbn的脚本比Mikaels的略快:

declare @a datetime
declare @x int = 1 
declare @mikaelend datetime

declare @mikael datetime = getdate() 
while @x < 5000000 
begin   
  select @a = dateadd(millisecond, -datepart(millisecond, getdate()), getdate()) , @x +=1 
end  
set @mikaelend = getdate()

set @x = 1 
declare @gbnend datetime
declare @gbn datetime = getdate() 
while @x < 5000000
begin 
  select @a = DATEADD(second, DATEDIFF(second, '20000101', getdate()), '20000101')  , @x +=1 
end  
set @gbnend = getdate()
select datediff(ms, @mikael, @mikaelend) mikael, datediff(ms, @gbn, @gbnend) gbn 

首次运行

mikael      gbn
----------- -----------
5320        4686

第二次运行

mikael      gbn
----------- -----------
5286        4883

第三次运行

mikael      gbn
----------- -----------
5346        4620

1
smalldatetime 截断到分钟。 (不确定我是否说得准确,也许我应该说它会四舍五入到分钟)。请参见(http://msdn.microsoft.com/en-us/library/bb677243.aspx)中的示例。不想对您进行投反对票,因为这是我尝试的内容,所以乍一看它*看起来*像是正确的答案 - 所以可以保留这个回答。 - Kyle Brandt
你是对的,我的错。smalldatetime 显示了秒,但它总是为0。 - t-clausen.dk
这样会更加公平:select datediff(ms, @mikael, @gbn) gbn, datediff(ms, @gbn, getdate()) mikael - Mikael Eriksson
@MikaelEriksson 我把测试搞砸了。现在已经更正了。 - t-clausen.dk
今天运行这个测试给了我相反的结果:mikael: 2426 gbn: 2950 // mikael: 2400 gbn: 2963 // mikael: 2450 gbn: 3010 - Horaciux

4
declare @dt datetime2
set @dt = '2019-09-04 17:24:05.784' 
select convert(datetime2(0), @dt)

这个方法会将毫秒四舍五入,而不是截断。问题要求一个方法,将2012-01-25 17:24:05.784转换为2012-01-25 17:24:05,而这个答案会得到2012-01-25 17:24:06 - Josh Gallagher

0
SELECT CAST( LEFT( '2018-07-19 11:59:59.999' , 19 ) AS DATETIME2(0) ) 

0
--- DOES NOT Truncate milliseconds
--- 2018-07-19 12:00:00.000
SELECT CONVERT(DATETIME, '2018-07-19 11:59:59.999')  

--- Truncate milliseconds
--- 2018-07-19 11:59:59.000
SELECT CONVERT(DATETIME, CONVERT(CHAR(19), '2018-07-19 11:59:59.999', 126)) 

--- Current Date Time with milliseconds truncated
SELECT CONVERT(DATETIME, CONVERT(CHAR(19), GETDATE(), 126)) 

0

在 @Mikael Eriksson 的回答基础上进行扩展:

要将 datetime2(7) 截断为 3 位(即毫秒):

   -- Strip of fractional part then add desired part back in
   select dateadd(nanosecond,
                  -datepart(nanosecond, TimeUtc) + datepart(millisecond, TimeUtc) * 1e6,
                  TimeUtc) as TimeUtc

目前datetime2(p)的最大精度为(7) (来自learn.microsoft.com)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接