MS SQL Server is dropping 1 millisecond from converted time [duplicate] - sql-server

This question already has answers here:
Why is SQL Server losing a millisecond?
(6 answers)
Closed 5 years ago.
The following query:
select convert(datetime, '2016-06-20 7:22:52.728')
gives me:
2016-06-20 07:22:52.727
In SQL Server v12.0.4100.1.
Whatever value I put for milliseconds, the result always has 1 less millisecond.
Am I missing something or is this a bug?

It's not a bug. The resolution of datetime is such that the final digit can only be one of a few values... Rounded to increments of .000, .003, or .007 seconds.
This is documented: Microsoft documentation for datetime (Transact-SQL)

That is how datetime works in sql server. If you want that millisecond, switch to datetime2([3-7]).
datetime accuracy is to 0.00333 second.
datetime2 accuracy is to 100 nanoseconds.
Date and Time Data Types and Functions (Transact-SQL)
Similarly, if you want to get the server time with additional accuracy, you would use sysdatetime() which returns datetime2(7) instead of getdate() which returns datetime.

Related

MS SQL Converting a String to Datetime issue [duplicate]

This question already has answers here:
Milliseconds wrong when converting from XML to SQL Server datetime
(2 answers)
DateTime vs DateTime2 Time Range Discrepancy
(3 answers)
Closed 1 year ago.
I'm trying to convert the string to datetime, but getting an unexpected result.
Select Convert(DateTime, '2015-08-10 13:08:01.725', 121);
Result:
2015-08-10 13:08:01.727
Note that the milliseconds have changed from 725 to 727.
I'm using Microsoft SQL Server 2014 (SP3-CU2) (KB4482960) - 12.0.6214.1 (X64).
This is expected, datetime is only accurate to 1/300 of a second, and .725 can't be represented by that. As a result it's rounded to the nearest 1/300, which would be .726666666666~, and then displayed as .727 as the display layer is accurate to 3 digits.
If you want to be accurate to 1/1000 of a second, use a more precise data type. datetime2(3) seems to be what you are after:
SELECT CONVERT(datetime2(3), '2015-08-10 13:08:01.725', 121);
This is because DATETIME is rounded to increments of .000, .003, or .007 seconds
Directly from Microsoft documentation

Correct week number from datepart [duplicate]

This question already has answers here:
Isoweek in SQL Server 2005
(4 answers)
Closed 7 years ago.
The code returns:
set datefirst 1
select datepart(wk,'2016-01-01') - 1
but
set datefirst 1
select datepart(wk,'2015-12-31')
returns..53 :/
But in fact - this is the same week. There is more days belonging to 2015 in this week, so it should be "53" or "1" (the same value) for any dates in this particular week. Is this possible to avieve this without building dedicated procedure to analyse date and adjust returned value ?
I use SQL Server 2005
You probably want iso_week:
set datefirst 1
select datepart(iso_week,'2015-12-31') --53
select datepart(iso_week,'2016-01-01') --53
LiveDemo
EDIT:
Looks like that iso_week is supported from SQL Server 2008+.
Is this possible to avieve this without building dedicated procedure
to analyse date and adjust returned value ?
Probably you need to write custom code to calculate it.

How to cast datetime into date in SQL Server 2005 [duplicate]

This question already has answers here:
How to return only the Date from a SQL Server DateTime datatype
(46 answers)
Closed 7 years ago.
I have used something like this:
select* from table where cast(CreatedDate as date) = cast(GETDATE() as DATE)
in SQL Server 2008R2 and it works perfectly. But when goes to 2005, it doesn't work because Date is not a defined system type. Can anyone let me know a way that works both 2005 and 2008R2?
The CreatedDate is default as current_timestamp and I want to get data with today's data only.
You can try this:
convert(DateTime, floor(convert(float, getdate())))
That gets rid of the time part, by converting it into the underlying float number and rounding down to the nearest integer. The integer part represents the date and the decimal part is the time, so converting the integer back to a DateTime give the same date you started with but without any time part.
You can also wrap it up as a scalar-valued function:
CREATE FUNCTION [dbo].[DateTrunc] (#date DateTime)
RETURNS DateTime
AS
BEGIN
return convert(DateTime, floor(convert(float, #date)))
END

Why CAST('20140904 23:59:59.999' AS datetime) equals '2014-09-05 00:00:00.000'? [duplicate]

This question already has answers here:
T-SQL Query Returning Items It Shouldn't Be
(5 answers)
Closed 8 years ago.
Try it for yourself, maybe it is somehow related to my environment:
The query:
SELECT CAST('20140904 23:59:59.999' AS datetime)
The result:
2014-09-05 00:00:00.000
Please explain this phenomenon.
UPDATE: Alex mentioned that datetime values are rounded to increments of .000, .003, or .007 seconds. The question is why?
datetime values are rounded to increments of .000, .003, or .007 seconds
I think you should use
SELECT CAST('20140904 23:59:59.997' AS datetime)
This returns:
2014-09-04 23:59:59.997
You can find more information here: http://msdn.microsoft.com/en-us/library/ms187819.aspx
This is the accuracy of datetime function in SQL.
You could probably use datetime2 if you are using a newer version of MSSQL as the accuracy for that is 100 nanosecs.
Datetime2: http://msdn.microsoft.com/en-us/library/bb677335.aspx
The increments are part of the API spec: See this link.
datetime values are rounded to increments of .000, .003, or .007
seconds, as shown in the following table.
I found this link which has at the end a better explanation. Quote:
Actually, SQL Server does store there the clock-ticks since midnight.
Each clock-tick is equivalent to 3.33 milliseconds. That’s also the
reason why the DATETIME datatype has an accuracy of one
three-hundredth of a second.
DATETIME is 2 x 4 bytes (date + time). The time part is stored as number of ticks since midnight. Each tick is 3.33 ms
If you need more precision, take a look at DATETIME2 type. DATETIME2 Accuracy is 100ns.

Milliseconds wrong when converting from XML to SQL Server datetime

I've run into a problem related to converting datetimes from XML (ISO8601: yyyy-mm-ddThh:mi:ss.mmm) to SQL Server 2005 datetime. The problem is when converting the milliseconds are wrong. I've tested both implicit and explicit conversion using convert(datetime, MyDate, 126) from nvarchar, and the result is the same:
Original Result
2009-10-29T15:43:12.990 2009-10-29 15:43:12.990
2009-10-29T15:43:12.991 2009-10-29 15:43:12.990
2009-10-29T15:43:12.992 2009-10-29 15:43:12.993
2009-10-29T15:43:12.993 2009-10-29 15:43:12.993
2009-10-29T15:43:12.994 2009-10-29 15:43:12.993
2009-10-29T15:43:12.995 2009-10-29 15:43:12.997
2009-10-29T15:43:12.996 2009-10-29 15:43:12.997
2009-10-29T15:43:12.997 2009-10-29 15:43:12.997
2009-10-29T15:43:12.998 2009-10-29 15:43:12.997
2009-10-29T15:43:12.999 2009-10-29 15:43:13.000
My non-extensive testing shows that the last digit is either 0, 3 or 7. Is this a simple rounding problem? Millisecond precision is important, and losing/gaining one or two is not an option.
Yes, SQL Server rounds time to 3.(3) milliseconds:
SELECT CAST(CAST('2009-01-01 00:00:00.000' AS DATETIME) AS BINARY(8))
SELECT CAST(CAST('2009-01-01 00:00:01.000' AS DATETIME) AS BINARY(8))
0x00009B8400000000
0x00009B840000012C
As you can see, these DATETIME's differ by 1 second, and their binary representations differ by 0x12C, that is 300 in decimal.
This is because SQL Server stores the time part of the DATETIME as a number of 1/300 second ticks from the midnight.
If you want more precision, you need to store a TIME part as a separate value. Like, store time rounded to a second as a DATETIME, and milliseconds or whatever precision you need as an INTEGER in another columns.
This will let you use complex DATETIME arithmetics, like adding months or finding week days on DATETIME's, and you can just add or substract the milliseconds and concatenate the result as .XXXXXX+HH:MM to get valid XML representation.
Because of the precision issues mentioned by Quassnoi if you have the option to use use SqlServer 2008 you can consider using datetime2 datatype or if you are only concerned about the time part you can use time datatype
Date and Time Data Types - lists all the types and theirs accuracy
In Sql Server 2005 if I needed precision of 1 millisecond I would add an extra column milisecond of type int to store the number of miliseconds and remove the miliseconds part from the dateTime column (set it to 000). That assuming that you need the date information as well.

Resources