DATEADD Nanoseconds: Round to datetime2 Ticks

DATEADD nanoseconds are rounded to the precision supported by the supplied datetime2 value. I test the rounding boundary instead of assuming every requested increment is stored. A datepart name does not establish single-nanosecond resolution.

A brass hourglass stands beside plain stacked papers and wooden storage boxes in a sunlit stone room.
A brass hourglass beside stacked papers and wooden storage boxes.

Start with an explicitly typed datetime2 value

The query supplies a datetime2(7) value at noon with a zero fractional second. That type supports seven fractional decimal places. Its smallest representable step is one hundred nanoseconds.

Every requested increment is a small nonnegative integer. The DATEADD expression uses the nanosecond datepart. It returns the same datetime2 type supplied by the date argument.

I cast the timestamp before applying DATEADD. A bare date string would invoke a different return-type rule. The explicit source type is part of the precision contract being demonstrated.

The final projection includes both formatted text and the stored fractional nanosecond value. The numeric column makes a zero increment distinguishable without relying only on a client’s fractional-second display.

WITH Increments AS
(
    SELECT CaseId,Nanoseconds FROM (VALUES (1,0),(2,1),(3,49),(4,50),(5,99),(6,100),(7,149),(8,150)) AS v(CaseId,Nanoseconds)
), Calculated AS
(
    SELECT *,DATEADD(nanosecond,Nanoseconds,CAST('2024-02-29T12:00:00.0000000' AS datetime2(7))) AS ResultTime
    FROM Increments
)
SELECT CaseId,Nanoseconds,CONVERT(varchar(27),ResultTime,126) AS ResultText,
    DATEPART(nanosecond,ResultTime) AS StoredFractionNanoseconds
FROM Calculated ORDER BY CaseId;
Native SSMS results showing datetime2 rounding of nanosecond increments to stored hundred-nanosecond units.
Increments below 50 nanoseconds round to zero. Values from 50 through 149 store 100 nanoseconds. The 150-nanosecond input rounds to 200, visible in the final seven-place fraction. Open the result at full size.

The first rounding threshold is fifty nanoseconds

Requested increments zero, one and forty-nine expect a stored fractional increment of zero. They do not move this datetime2(7) value to the next representable step. That is the expected rounding behavior.

Requested increments fifty and ninety-nine expect one hundred nanoseconds. A request of exactly one hundred also expects that same stored fraction. Several different requested increments therefore produce one stored result.

The formatted results for those positive stored steps end in .0000001. That final digit represents one ten-millionth of a second. It does not represent one nanosecond.

I keep requests on both sides of the threshold in the model. Testing only an exact hundred-nanosecond increment would conceal the rounding decision. The forty-nine and fifty cases expose the boundary directly.

The next threshold continues the quantization

A request of one hundred forty-nine expects a stored fraction of one hundred nanoseconds. A request of one hundred fifty expects two hundred. The second threshold produces another representable step.

The final formatted value therefore ends in .0000002. The expected numeric fraction is two hundred. Both columns describe the same resulting timestamp at different display units.

The sample starts at an exact fractional boundary so the calculation is easy to review. It does not measure clock accuracy or event timing. These are deterministic arithmetic expectations for supplied literals.

The display conversion can omit the all-zero fraction under the selected ISO style. That formatting detail does not change the stored value. The numeric fraction column remains zero for those first cases.

Nanosecond requests and stored result

Do not turn precision into an event-identity promise

Distinct requested times can map to the same representable timestamp. A timestamp alone may therefore be insufficient as an event tie-breaker. An ordering requirement can need a separate unique identifier.

The precision of stored datetime2 is also separate from the accuracy of a source clock. A precise representation does not prove an observation was measured accurately. This example examines arithmetic rather than measurement quality.

Other date and time types have different supported precision and dateparts. This example deliberately uses datetime2(7). It does not generalize the result to datetime or date values.

The query uses made-up increments and changes no settings or tables. It does not test negative rounding or values near the type’s range boundary. Those cases require their own explicit expectations.

When adapting fine-grained time arithmetic, retain values immediately below and at each relevant rounding threshold. Match the input type to the required stored precision. Then keep representation precision separate from the application’s event-order and clock-accuracy requirements.

Try the forty-nine and fifty cases yourself and watch the stored value jump.

A nanosecond argument is not a nanosecond storage guarantee, it is rounded to the value’s supported precision.

Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.


Discover more from SQL Authority with Pinal Dave

Subscribe to get the latest posts sent to your email.

SQL DateTime, SQL Function, SQL Server
Previous Post
Oracle to SQL Server: Translating NVL, ROWNUM and Sequences
Next Post
SQL SERVER – Mirrored Backup and Restore and Split File Backup – Introduction

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.