Reputation: 67355
The following queries:
DECLARE @__dateRange_StartDate_4 DATETIME ='2021-03-01T00:00:00.000'
DECLARE @__dateRange_EndDate_3 DATETIME ='2021-03-31T23:59:59.999'
SELECT DATEDIFF(DAY, '2021-03-01T00:00:00.000', '2021-03-31T23:59:59.999') + 1
SELECT DATEDIFF(DAY, @__dateRange_StartDate_4, @__dateRange_EndDate_3) + 1
SELECT @__dateRange_EndDate_3
Produces the following results:
31
32
2021-04-01 00:00:00.000
It appears @__dateRange_EndDate_3
is being rounded to the next day, which I don't want.
What is the correct way to have the second SELECT
return 31?
Note: My queries are actually being called from Entity Framework so I may be limited to what I can do here, but I at least want to understand the issue as this was unexpected.
Upvotes: 1
Views: 1299
Reputation: 755541
DATETIME
in SQL Server has an accuracy of 3.33ms (0.003 seconds) - therefore, the "highest" possible value for March 31, 2021 would be 2021-03-31T23:59:59.997
- anything beyond that will be rounded up to the next day.
This is just one of the reasons why as of SQL Server 2008 the general recommendation is to use DATE
for when you don't need any time portion, or DATETIME2(n)
(when you need the time portion; n
is the number of fractional digits after the second - can be 0 through 7) datatypes.
DATETIME2(n)
offers accuracy down to 100 ns and thus 2021-03-31T23:59:59.999
will be absolutely no problem in a DATETIME2(3)
column.
As an added benefit, DATETIME2(n)
also doesn't have this "arbitrary" lower limits of supported dates only through 01.01.1753 - with DATETIME2(n)
you can store any date, back to 1 AD
Upvotes: 4
Reputation: 1271231
This is silly. Don't bother with trying to get the last increment before a time -- and learning that datetime
is only accurate to 0.003 seconds.
Express the logic only using dates:
DECLARE @__dateRange_StartDate_4 DATE ='2021-03-01'
DECLARE @__dateRange_EndDate_3 DATE ='2021-04-01'
SELECT DATEDIFF(DAY, '2021-03-01', '2021-04-01');
SELECT DATEDIFF(DAY, @__dateRange_StartDate_4, @__dateRange_EndDate_3);
SELECT @__dateRange_EndDate_3;
Then use these with inequalities:
WHERE date >= @__dateRange_StartDate_4 AND
date < @__dateRange_EndDate_3
Inequalities -- with >=
and <
is the recommended way to handle date/time comparisons. Dealing with the "last increment" problem is only one of the problems it solves.
If you really are committed to figuring out the last increment before midnight, you can use DATETIME2
or .997
. But I don't recommend either of those approaches. Here is a db<>fiddle.
Upvotes: 1