Question

I ran into a situation where I wanted to get the difference between 2 datetime2(7)s and a time(7). The issue was that subtraction of a datetime2 is not supported.

 

DATEDIFF(ns, 0, cast('2015-01-01 00:00:00.0000000' as datetime2(7))) wouldn't work for converting to nanoseconds because int doesn't support that large of a value and DATEDIFF)BIG doesn't exist until SQL Server 2016 and I didn't want to extract each individual DATEPART the reconstruct the value after getting the differences from each section.

 

So I wrote a few scalar functions for SQL to allow conversion between the 3 formats. They're listed below, hopefully this helps someone. :)

 

CREATE FUNCTION [BigIntToDateTime2](@ticks bigint, @precision binary(1))
RETURNS DATETIME2(7)
WITH SCHEMABINDING AS
BEGIN
declare @dtTime bigint = @ticks % 864000000000;
declare @dtDays bigint = (@ticks - @dtTime) / 864000000000;
declare @dtTimeBytes binary(5) = CAST(REVERSE(CONVERT(binary(5), @dtTime)) as binary(5))
declare @dtDaysBytes binary(3) = CAST(REVERSE(CONVERT(binary(3), @dtDays)) as binary(3))

return CAST(CAST(@precision + @dtTimeBytes + @dtDaysBytes as binary(9)) as datetime2(7))
END


CREATE FUNCTION [BigIntToTime](@ticks BIGINT, @precision binary(1))
RETURNS TIME(7)
WITH SCHEMABINDING AS
BEGIN
declare @dtTimeBytes binary(5) = CAST(REVERSE(CONVERT(binary(5), @ticks)) as binary(5))

return CAST(CAST(@precision + @dtTimeBytes as binary(6)) as time(7))
END


CREATE FUNCTION [DateTime2ToBigInt](@dt DATETIME2(7))
RETURNS BIGINT
WITH SCHEMABINDING AS
BEGIN
declare @dtBinary binary(9) = CAST(REVERSE(CONVERT(binary(9), @dt)) as binary(9));
declare @dtDateBytes binary(3) = SUBSTRING(@dtBinary, 1, 3);
declare @dtTimeBytes binary(5) = SUBSTRING(@dtBinary, 4, 5);
declare @dtPrecisionByte binary(1) = SUBSTRING(@dtBinary, 9, 1);

return (CONVERT(bigint, @dtDateBytes) * 864000000000) + CONVERT(bigint, @dtTimeBytes)
END


CREATE FUNCTION [DateTime2ToTime](@dt datetime2(7))
RETURNS TIME(7)
WITH SCHEMABINDING AS
BEGIN
declare @dtBinary binary(9) = CONVERT(binary(9), @dt)
declare @dtTimeBytes binary(5) = SUBSTRING(@dtBinary, 2, 5);
declare @dtPrecisionByte binary(1) = SUBSTRING(@dtBinary, 1, 1);

return cast(@dtPrecisionByte + @dtTimeBytes as time(7))
END


CREATE FUNCTION [TimeToDateTime2](@time TIME(7))
RETURNS DATETIME2(7)
WITH SCHEMABINDING AS
BEGIN
return CAST(CAST(@time as binary(9)) as datetime2(7))
END


CREATE FUNCTION [TimeToBigInt](@time TIME(7))
RETURNS BIGINT
WITH SCHEMABINDING AS
BEGIN
declare @timeBytes binary(5) = SUBSTRING(CAST(REVERSE(CAST(@time as BINARY(6))) as binary(6)), 1, 5)

return CAST(@timeBytes as bigint)
END

 

 

 

 

 

Examples:

declare @dt2 datetime2(7) = '2015-01-01 00:04:21.3420544'

declare @dt2bi bigint = (SELECT [dbo].[DateTime2ToBigInt](@dt2))
declare @bidt2 datetime2(7) = (SELECT [dbo].[BigIntToDateTime2](@dt2bi, 7))
declare @dt2t time(7) = (SELECT [dbo].[DateTime2ToTime](@dt2))
declare @tdt2 datetime2(7) = (SELECT [dbo].[TimeToDateTime2](@dt2t))
declare @tbi bigint = (SELECT [dbo].[TimeToBigInt](@dt2t))
declare @bit time(7) = (SELECT [dbo].[BigIntToTime](@tbi, 7))


select @dt2bi as [DateTime2ToBigInt]
select @bidt2 as [BigIntToDateTime2]
select @dt2t as [DateTime2ToTime]
select @tdt2 as [TimeToDateTime2]
select @tbi as [TimeToBigInt]
select @bit as [BigIntToTime]

 

Edited by Squirrelington

2 answers to this question

Recommended Posts

  • 0

Forgot to explain my end scenario entirely. I had a sessionstart datetime2(7), sessionend datetime2(7) and an idletime time(7) and I wanted to take (sessionend - sessionstart) - idletime and show it as a time(7) of the activetime.

 

[dbo].[BigIntToTime]([dbo].[DateTime2ToBigInt]([SessionEnd]) - [dbo].[DateTime2ToBigInt]([SessionStart]) - [dbo].[TimeToBigInt]([IdleTime]), 0x07) as [ActiveTime]

 

I eventually wrapped it into a view.

Edited by Squirrelington
  • 0

This is C# code but is related, I used this when I was figuring out what bytes equaled what. It is a DateTime2, Time, Int24 and Int40 structure for C#.

 


    [StructLayout(LayoutKind.Explicit)]
    [Serializable]
    public struct DateTime2
    {
        [FieldOffset()]
        public byte Precision;
        [FieldOffset(1)]
        public Int40 Ticks;
        [FieldOffset(6)]
        public Int24 Days;

        public DateTime2(byte[] data)
        {
            if (data.Length >= 9)
            {
                Precision = data[];
                Ticks = new Int40(data, 1);
                Days = new Int24(data, 6);
            }
            else
                throw new ArgumentException();
        }

        public DateTime ToDateTime()
        {
            return new DateTime(Ticks.Value).AddDays(Days.Value);
        }
    }

    [StructLayout(LayoutKind.Explicit)]
    [Serializable]
    public struct Time
    {
        [FieldOffset()]
        public byte Precision;
        [FieldOffset(1)]
        public Int40 Ticks;

        public Time(byte[] data)
        {
            if (data.Length >= 6)
            {
                Precision = data[];
                Ticks = new Int40(data, 1);
            }
            else
                throw new ArgumentException();
        }

        public DateTime ToDateTime()
        {
            return new DateTime(Ticks.Value);
        }
    }

    [StructLayout(LayoutKind.Explicit)]
    [Serializable]
    public struct Int24
    {
        [FieldOffset()]
        private byte _b0;
        [FieldOffset(1)]
        private byte _b1;
        [FieldOffset(2)]
        private byte _b2;

        public unsafe Int24(byte[] number, int startIndex = )
        {
            if (number.Length < 3)
                throw new ArgumentException();

            _b0 = new byte();
            _b1 = new byte();
            _b2 = new byte();
            fixed (byte* n = number)
            {
                _b0 = *(n + startIndex);
                _b1 = *(n + startIndex + 1);
                _b2 = *(n + startIndex + 2);
            }
        }

        public int Value
        {
            get
            {
                return _b0 |
                    (_b1 << 8) |
                    (_b2 << 16);
            }
        }

        public override string ToString()
        {
            return Value.ToString();
        }
    }

    [StructLayout(LayoutKind.Explicit)]
    [Serializable]
    public struct Int40
    {
        [FieldOffset()]
        private byte _b0;
        [FieldOffset(1)]
        private byte _b1;
        [FieldOffset(2)]
        private byte _b2;
        [FieldOffset(3)]
        private byte _b3;
        [FieldOffset(4)]
        private byte _b4;

        public unsafe Int40(byte[] number, int startIndex = )
        {
            if (number.Length < 5)
                throw new ArgumentException();

            _b0 = new byte();
            _b1 = new byte();
            _b2 = new byte();
            _b3 = new byte();
            _b4 = new byte();
            fixed (byte* n = number)
            {
                _b0 = *(n + startIndex);
                _b1 = *(n + startIndex + 1);
                _b2 = *(n + startIndex + 2);
                _b3 = *(n + startIndex + 3);
                _b4 = *(n + startIndex + 4);
            }
        }

        public long Value
        {
            get
            {
                return _b0 |
                    ((long)_b1 << 8) |
                    ((long)_b2 << 16) |
                    ((long)_b3 << 24) |
                    ((long)_b4 << 32);
            }
        }

        public override string ToString()
        {
            return Value.ToString();
        }
    }

 

This topic is now closed to further replies.
  • Posts

    • A few things I am wondering about for S3: A.  What's Pike doo gonna look like this time around....yea I've watched the trailers & it looks poofed up, but still.... B. When will the unintelligible, physco-babbling Pelia go away (or at least learn how to speak English properly, without that crappy, slurred accent that sounds like she's on crack, Mary Jane, & LSD at the same time) ?  Hopefully Scotty's arrival will mean her departure is near.... C.  When do we get to see more of the stunningly gorgeous No. 1, preferably in regular/civilian clothes that show off her physical attributes better ? D. Is Spock EVER gonna get laid properly, human style ?  I feel certain that Christine could make any Vulcan-human horizontal bomp a thing to remember for a LONG time  E.  Can we PLEEEEEEZE get rid of the hatchet-head/buzz cut hair styles on Ortega & anyone else that has it....  But otherwise, as Pike says:  HIT IT !  
    • RIP Hotlips..... IMHO, her best scenes were the few where she dared to let her REAL feminine side show through from underneath all that crappy, worn-torn soldier facade that she had to keep up with...she instantly lit up every room or situation where she was featured !
    • Helium Converter 3.3.69.0 by Razvan Serea Helium Converter is a free Windows utility for converting audio files between formats such as MP3, FLAC, AAC, WMA, OGG, and WAV. It supports batch conversion, preserves or updates tag information, and offers features like volume normalization. With a simple interface, it's ideal for users who need to convert large music libraries quickly and efficiently while retaining metadata. Helium Converter key features: Supports file formats: MP3, MP4, FLAC, AAC, M4A, WMA, WAV, OGG, OPUS, APE.... Batch conversion for large music libraries Preserves and edits metadata (ID3, Vorbis Comments, etc.) Volume normalization to equalize loudness Album art extraction and embedding Drag-and-drop interface for quick file selection Adjustable encoding parameters (bitrate, sample rate, channels) Uses internal codecs for consistent performance Supports CUE sheets for split track conversion File renaming based on tags during export Unicode support for international file and tag names Logging of conversion processes for troubleshooting Multi-core CPU support for faster conversions Download: Helium Converter 3.3.69.0 | 25.1 MB (Freeware) Links: Helium Converter Home Page | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • Since it's been quite a while since the last episode aired, would it be fair (or cruel) to refer to Peggy as a MILF, or even a SMILF ?  HAHAHAHAHAHA
    • Their computers are not gonna stop working in October
  • Recent Achievements

    • One Year In
      WaynesWorld earned a badge
      One Year In
    • First Post
      chriskinney317 earned a badge
      First Post
    • Week One Done
      Nullun earned a badge
      Week One Done
    • First Post
      sultangris earned a badge
      First Post
    • Reacting Well
      sultangris earned a badge
      Reacting Well
  • Popular Contributors

    1. 1
      +primortal
      172
    2. 2
      ATLien_0
      122
    3. 3
      snowy owl
      121
    4. 4
      Xenon
      117
    5. 5
      +Edouard
      93
  • Tell a friend

    Love Neowin? Tell a friend!