Конвертировать DateTime в шестнадцатеричный эквивалент в VB.NET - PullRequest
2 голосов
/ 14 сентября 2011

Как мне добиться того же в VB.NET, что так легко сделать в SQL Server.

SELECT CAST(GETDATE() AS VARBINARY(8)) --GIVES THE CURRENT TIME IN HEX

Теперь у меня вопрос, как я могу создать такую ​​же строку в VB.NET, чтобы я мог сравнивать в SQL Server как таковой -

SELECT CASE WHEN GETDATE()=CAST(0X00009F5E00D8DF7C AS DATETIME) THEN 'TRUE' ELSE 'FALSE' END -- 0X00009F5E00D8DF7C WILL BE THE VALUE I GET IN VB.NET WHEN I CONVERT IT DATE.NOW() TO HEX

Ответы [ 3 ]

3 голосов
/ 15 сентября 2011

Этот ответ просто касается преобразования .NET DateTimes в двоичный формат, который эквивалентен типу данных datetime SQL Server, поэтому я считаю, что он достаточно отличается, что требует отдельного ответа (я проверил здесь и здесь , чтобы убедиться, что все в порядке).

Как отметил @Martin Smith, двоичный формат datetime - это не просто число тактов с определенного момента времени.

datetime хранится в виде 8 байтов, первые 4 байта - это количество дней с 01-01-1900, а вторые 4 байта - это число "тиков" с полуночи того дня, где тик равен 10/3 миллисекунды.

Чтобы преобразовать .NET DateTime в эквивалентное двоичное представление, нам нужно определить количество дней с '01 -01-1900 ', преобразовать его в шестнадцатеричное число, а затем число тиков с полуночи, что немного сложнее, поскольку тик .NET равен 100 нс.

Например:

DateTime dt = DateTime.Now;
DateTime zero = new DateTime(1900, 1, 1);

TimeSpan ts = dt - zero;
TimeSpan ms = ts.Subtract(new TimeSpan(ts.Days, 0, 0, 0));

string hex = "0x" + ts.Days.ToString("X8") + ((int)(ms.TotalMilliseconds/3.33333333)).ToString("X8");

Когда я запускал этот код, dt был 9/14/2011 23:19:03.366, и он устанавливал hex в 0x00009F5E01804321, что в SQL Server преобразовывалось в 2011-09-14 23:19:03.363.

Я полагаю, что у вас всегда будут проблемы с получением точной даты из-за округления, но если вы можете использовать запрос, в котором дата и время не должны точно совпадать, вплоть до миллисекунды, это может быть достаточно близко.

Редактировать

В своем комментарии под первым опубликованным ответом я спросил о SQL Server 2008, потому что тип данных datetime2 хранит время с точностью до 100 нс (по крайней мере, с точностью по умолчанию), что соответствует хорошо с .NET. Если вам интересно, как это хранится на двоичном уровне в SQL Server, см. мой ответ на старый вопрос.

1 голос
/ 25 июля 2013

Мне пришлось преобразовать некоторые даты в dbscript из строки шестнадцатеричного формата SQL Server в стандартную строку даты и времени (для использования с переводом скриптов TSQL в MySQL).Я использовал некоторые коды, которые я искал здесь и придумал:

        static string HexDateTimeToDateTimeString(string dateTimeHexString)
    {
        string datePartHexString = dateTimeHexString.Substring(0, 8);
        int datePartInt = Convert.ToInt32(datePartHexString, 16);
        DateTime dateTimeFinal = (new DateTime(1900, 1, 1)).AddDays(datePartInt);

        string timePartHexString = dateTimeHexString.Substring(8, 8);
        int timePartInt = Convert.ToInt32(timePartHexString, 16);
        double timePart = timePartInt * 10 / 3;
        dateTimeFinal = dateTimeFinal.AddMilliseconds(timePart);

        return dateTimeFinal.ToString();
    }

    static string HexDateToDateString(string dateHexString)
    {
        int days = byte.Parse(dateHexString.Substring(0, 2), NumberStyles.HexNumber)
                   | byte.Parse(dateHexString.Substring(2, 2), NumberStyles.HexNumber) << 8
                   | byte.Parse(dateHexString.Substring(4, 2), NumberStyles.HexNumber) << 16;
        DateTime dateFinal = new DateTime(1, 1, 1).AddDays(days);
        return dateFinal.Date.ToString(); 
    }

Возможно, не оптимизирован, но показывает идею.

1 голос
/ 15 сентября 2011

Я склоняюсь к тому, чтобы клиенты не создавали SQL-операторы для выполнения вашим уровнем доступа к данным, но, предполагая, что вам нужно что-то работать в ближайшее время, вы можете вместо этого использовать параметризованный запрос.

Если вы выполняете вызовы методов от клиента (ов) к другим уровням вашего приложения, вы можете создать SqlCommand на клиенте и передать его следующему уровню, где он будет выполняться.

VB.NET - это не тот язык, который я обычно использую, поэтому, пожалуйста, простите за любые синтаксические ошибки.

На клиенте:

Dim dateValue As Date = DateTime.Now
Dim queryText As String = "SELECT CASE WHEN GETDATE() = @Date THEN 'True' ELSE 'False' END"
Dim command As SqlCommand = New SqlCommand(queryText)

command.Parameters.AddWithValue("@Date", dateValue)

Если вам необходимо отправить строку, вы можете преобразовать DateTime в строку на клиенте, а затем преобразовать обратно в DateTime на уровне доступа к данным, используя общий формат.

На клиенте:

Dim queryText As String = "SELECT CASE WHEN GETDATE() = @Date THEN 'True' ELSE 'False' END"
Dim dateValue As Date = DateTime.Now
Dim dateString = DateTime.Now.ToString("M/d/yyyy H:mm:ss.fff", DateTimeFormatInfo.InvariantInfo)

Затем отправьте queryText и dateString на следующий уровень в вашем приложении, где он преобразуется обратно в Date и снова использует параметризованный запрос:

Dim dateValue As Date

Date.TryParseExact(dateString, "M/d/yyyy H:mm:ss.fff", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, dateValue)
Dim command As SqlCommand = New SqlCommand(queryText)

command.Parameters.AddWithValue("@Date", dateValue)

Если ваши клиенты находятся в разных часовых поясах, вам следует (как упомянул @Martin Smith) использовать время UTC.

В .NET

Dim dateValue = DateTime.UtcNow

, а также в вашем запросе, используя GETUTCDATE():

Dim queryText As String = "SELECT CASE WHEN GETUTCDATE() = @Date THEN 'True' ELSE 'False' END"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...