如果我有2010-03-01 17:34:12.018这样的日期值将此转换为2010-03-01 00:00:00.000的最有效方法是什么?第二个问题是,模拟Oracle的TRUNC函数的最佳方法是什么,该函数允许您在年、季度、月、周、日、小时、分钟和秒边界进行截断?
2010-03-01 17:34:12.018
2010-03-01 00:00:00.000
TRUNC
6ie5vjzr1#
要舍入到最近的全天,有三种方法广泛使用。第一个使用datediff来查找自0日期时间以来的天数。0日期时间对应于1900年1月1日。通过将日差添加到开始日期,您将四舍五入为一整天;
datediff
0
select dateadd(d, 0, datediff(d, 0, getdate()))
第二种方法是基于文本的:它用varchar(10)截断文本描述,只留下日期部分:
varchar(10)
select convert(varchar(10),getdate(),111)
第三种方法使用的事实是,datetime实际上是一个浮点数,表示1900年以来的天数。因此,通过将其四舍五入为整数,例如使用floor,您可以得到一天的开始:
datetime
floor
select cast(floor(cast(getdate() as float)) as datetime)
要回答你的第二个问题,本周的开始更为棘手。一种方法是减去星期几:
select dateadd(dd, 1 - datepart(dw, getdate()), getdate())
这也会返回一个时间部分,因此您必须将其与时间剥离方法之一结合起来才能获得第一次约会。例如,将@start_of_day作为可读性变量:
@start_of_day
declare @start_of_day datetime set @start_of_day = cast(floor(cast(getdate() as float)) as datetime) select dateadd(dd, 1 - datepart(dw, @start_of_day), @start_of_day)
年、月、小时和分钟的开始仍然适用于“1900年以来的差异”方法:
select dateadd(yy, datediff(yy, 0, getdate()), 0) select dateadd(m, datediff(m, 0, getdate()), 0) select dateadd(hh, datediff(hh, 0, getdate()), 0) select dateadd(mi, datediff(mi, 0, getdate()), 0)
按秒舍入需要不同的方法,因为从0开始的秒数会导致溢出。一种方法是使用一天的开始,而不是1900年作为参考日期:
declare @start_of_day datetime set @start_of_day = cast(floor(cast(getdate() as float)) as datetime) select dateadd(s, datediff(s, @start_of_day, getdate()), @start_of_day)
要舍入5分钟,请调整分钟舍入方法。取微小差值的商,例如使用/5*5:
/5*5
select dateadd(mi, datediff(mi,0,getdate())/5*5, 0)
这也适用于一刻半小时。
thtygnil2#
如果您使用的是SQL Server 2008+,则可以使用Date数据类型,如下所示:
Date
select cast(getdate() as date)
如果仍然需要将值设置为DateTime数据类型,可以执行以下操作:
DateTime
select cast(cast(getdate() as date) as datetime)
一种适用于所有版本的SQL Server的方法是:
lmvvr0a83#
尝试:
SELECT DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)
**更新:**第二个问题的答案:多年来,你可以使用我的答案的一个稍微修改的版本:
SELECT DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
季度:
SELECT DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)
等等我检查了几分钟,没关系。但几秒钟后,我收到一条溢出消息:两个日期时间列的差异导致运行时溢出。
**另一个更新:**请查看同一问题的以下答案
r6hnlfcb4#
这很晚了,但会产生帖子中要求的准确结果。我也觉得它比使用dateadd更直观,但这是我的偏好。
declare @SomeDate datetime = '2010-03-01 17:34:12.018' SELECT DATEFROMPARTS( YEAR(@SomeDate) ,MONTH(@SomeDate) ,'01' ) AS CUR_DATE_FROM_PARTS ,DATETIMEFROMPARTS( YEAR(@SomeDate) ,MONTH(@SomeDate) ,'01' --DAY(@SomeDate) ,'00' --DATEPART(HOUR,@SomeDate) ,'00' --DATEPART(MINUTE,@SomeDate) ,'00' --DATEPART(SECOND,@SomeDate) ,'00' --DATEPART(MILLISECOND,@SomeDate) ) AS CUR_DATETIME_FROM_PARTS ,@SomeDate AS CUR_DATETIME ,YEAR(@SomeDate) AS CUR_YEAR ,MONTH(@SomeDate) AS CUR_MONTH ,DAY(@SomeDate) AS CUR_DAY ,DATEPART(HOUR,@SomeDate) AS CUR_HOUR ,DATEPART(MINUTE,@SomeDate) AS CUR_MINUTE ,DATEPART(SECOND,@SomeDate) AS CUR_SECOND ,DATEPART(MILLISECOND,@SomeDate) AS CUR_MILLISECOND FROM Your_Table
截短日期:2010-03-01截短日期时间:2010-03-01 00:00:00.000日期时间:2010-03-01 17:34:12.017
pbossiut5#
不确定这是否是最有效的,但我喜欢在@SomeDate是您的字段的情况下使用下面的简单性。
Concat(Year(@SomeDate), '-', Month(@SomeDate), '-', '01')
nbewdwxp6#
如果您想以独立于SET DATEFIRST的方式将日期截断到周开始,您可以:
SET DATEFIRST
--change a date backwards to nearest Monday DATEADD(DAY, (DATEPART(dw, '2001-01-01') - DATEPART(dw, YOUR_COLUMN)-7)%7, YOUR_COLUMN)
细分如下:
DATEPART(dw, '2001-01-01') - DATEPART(dw, YOUR_COLUMN)
dw
( ... -7)%7
1
2
dw_for_known_monday - dw_for_your_date
+1
-6
7
-7
DATEADD
DATEADD(DAY, (DATEPART(dw, '2001-01-01') - DATEPART(dw, YOUR_COLUMN)-7)%7, YOUR_COLUMN)
如果你想把日期倒转到星期天,那么把日期2001-01-01改为已知的星期天(如2000-12-31),等等
2001-01-01
2000-12-31
6条答案
按热度按时间6ie5vjzr1#
要舍入到最近的全天,有三种方法广泛使用。第一个使用
datediff
来查找自0
日期时间以来的天数。0
日期时间对应于1900年1月1日。通过将日差添加到开始日期,您将四舍五入为一整天;第二种方法是基于文本的:它用
varchar(10)
截断文本描述,只留下日期部分:第三种方法使用的事实是,
datetime
实际上是一个浮点数,表示1900年以来的天数。因此,通过将其四舍五入为整数,例如使用floor
,您可以得到一天的开始:要回答你的第二个问题,本周的开始更为棘手。一种方法是减去星期几:
这也会返回一个时间部分,因此您必须将其与时间剥离方法之一结合起来才能获得第一次约会。例如,将
@start_of_day
作为可读性变量:年、月、小时和分钟的开始仍然适用于“1900年以来的差异”方法:
按秒舍入需要不同的方法,因为从
0
开始的秒数会导致溢出。一种方法是使用一天的开始,而不是1900年作为参考日期:要舍入5分钟,请调整分钟舍入方法。取微小差值的商,例如使用
/5*5
:这也适用于一刻半小时。
thtygnil2#
如果您使用的是SQL Server 2008+,则可以使用
Date
数据类型,如下所示:如果仍然需要将值设置为
DateTime
数据类型,可以执行以下操作:一种适用于所有版本的SQL Server的方法是:
lmvvr0a83#
尝试:
**更新:**第二个问题的答案:多年来,你可以使用我的答案的一个稍微修改的版本:
季度:
等等
我检查了几分钟,没关系。但几秒钟后,我收到一条溢出消息:
两个日期时间列的差异导致运行时溢出。
**另一个更新:**请查看同一问题的以下答案
r6hnlfcb4#
这很晚了,但会产生帖子中要求的准确结果。我也觉得它比使用dateadd更直观,但这是我的偏好。
截短日期:2010-03-01
截短日期时间:2010-03-01 00:00:00.000
日期时间:2010-03-01 17:34:12.017
pbossiut5#
不确定这是否是最有效的,但我喜欢在@SomeDate是您的字段的情况下使用下面的简单性。
nbewdwxp6#
如果您想以独立于
SET DATEFIRST
的方式将日期截断到周开始,您可以:细分如下:
DATEPART(dw, '2001-01-01') - DATEPART(dw, YOUR_COLUMN)
:已知星期一(2001-01-01是星期一)的dw
减去你的日期的m1o3p,有效地给出了“你的日期和星期一之间的天数差”或“我们要把你的日期滚动到星期一还要多少天”( ... -7)%7
-我们从中减去7,并将结果乘以7。dw
就是1
,而您已知的星期一是2
。dw_for_known_monday - dw_for_your_date
的结果是+1
而不是-6
7
,那么结果肯定是负数,但我们不希望你的周一(与已知的周一不同0天)以-7
的DATEADD
结束,因此我们将结果乘以7。-7
转换为0
,这意味着DATEADD
只会在-6
和0
之间有一个“天数”参数DATEADD(DAY, (DATEPART(dw, '2001-01-01') - DATEPART(dw, YOUR_COLUMN)-7)%7, YOUR_COLUMN)
-然后我们用DATEADD
计算上述步骤中的(负)天数如果你想把日期倒转到星期天,那么把日期
2001-01-01
改为已知的星期天(如2000-12-31
),等等