在VB.NET中将DateTime转换为Hex等效项

时间:2011-09-14 07:51:58

标签: vb.net sql-server-2005 sql-server-2008 datetime

如何在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 个答案:

答案 0 :(得分:3)

这个答案只是简单地将.NET DateTimes转换为等同于SQL Server的datetime数据类型的二进制格式,所以我认为它有足够的不同以保证单独的答案(我检查了herehere以确定没问题。)

正如@Martin Smith指出的那样,datetime的二进制格式不仅仅是自特定时间点以来的一些滴答。

datetime存储为8个字节,前4个字节是自01-01-1900以来的天数,第二个4个字节是自当天午夜以来的“滴答”数,其中a tick是10/3毫秒。

为了将.NET DateTime转换为等效的二进制表示,我们需要确定自'01 -01-1900'以来的天数,将其转换为十六进制,然后是从午夜开始的滴答数,这是因为.NET滴答是100ns,所以有点复杂。

例如:

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");

当我运行此代码时,dt9/14/2011 23:19:03.366,并将hex设置为0x00009F5E01804321,在SQL Server中转换为2011-09-14 23:19:03.363

我相信由于四舍五入会得到确切的日期总是有问题,但是如果你可以使用一个查询,其中日期时间不必完全匹配,直到毫秒,这可能足够接近。

修改

在我发布的第一个答案的评论中,我询问了SQL Server 2008,因为datetime2数据类型确实存储的时间精度为100ns(至少是默认精度),与.NET很好地匹配。如果您对SQL Server中二进制级别的存储方式感兴趣,请参阅my answer以查看较旧的问题。

答案 1 :(得分:1)

我的第一个倾向是客户端不应该构建由数据访问层执行的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)

然后将queryTextdateString发送到应用程序中的下一层,它将转换回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"

答案 2 :(得分:1)

我不得不将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(); 
    }

可能没有优化,但显示了这个想法。