如何从Date变量中删除几分之一秒?

时间:2018-12-10 14:58:54

标签: vba ms-access access-vba odbc

背景:

我从Active Directory中读取了pwdLastSet属性,并希望将其存储在SQL Server表的DATETIME2(0)列中。我不想存储几分之一秒。

这是一个8字节的整数,自1601年1月1日凌晨12:00开始以100纳秒的步长表示。我使用this function将其转换为Date变量。

使用ODBC-call failed继续失败,并且花了我很多时间才能确定该函数返回的额外精度导致了错误。

问题:

Date变量中删除几分之一秒的最佳方法是什么?


如何复制:

我使用SQL Server 2008 R2和Access2010。
在SQL Server中:

CREATE TABLE TestDT (
    ID      INT             NOT NULL,
    colDT2  DATETIME2(0)    NULL,

    CONSTRAINT PK_TestDT PRIMARY KEY (ID)
)
GO
INSERT TestDT (ID) VALUES (1)
GO

使用Native Client ODBC驱动程序或当前的Microsoft ODBC Driver 17 for SQL Server将表链接到Access。默认的“ SQL Server”驱动程序实际上并不知道如何使用DATETIME2。

在Access VBA中:

Public Sub TestDT()

    Dim DB As DAO.Database
    Dim RS As DAO.Recordset
    Dim dte As Date
    Dim i As Long

    Set DB = CurrentDb

    ' Random date+time
    dte = CDate("2018-12-24 15:16:17")

    ' 1st iteration: write original date+time -> works
    ' 2nd iteration: try to write date+time with fractional seconds -> error for DATETIME2(0) column

    For i = 1 To 2
        If i = 2 Then
            ' Introduce milliseconds nastiness
            dte = dte + 0.00001
        End If
        Debug.Print "Iteration " & i, Format(dte, "yyyy-mm-dd hh:nn:ss")

        Set RS = DB.OpenRecordset("SELECT * FROM TestDT WHERE ID = 1", dbOpenDynaset)

        With RS
            .Edit
            !colDT2 = dte
            On Error Resume Next
            .Update

            If Err.Number <> 0 Then
                Debug.Print "Error " & Err.Number, Err.Description
                ' The DAO Errors collection shows the actual error
                Debug.Print Errors(0).Description
            Else
                Debug.Print "Update OK"
            End If
            On Error GoTo 0

            .Close
        End With
    Next i

End Sub

输出:

Iteration 1   2018-12-24 15:16:17
Update OK
Iteration 2   2018-12-24 15:16:18
Error 3146    ODBC-Aufruf fehlgeschlagen.
[Microsoft][ODBC Driver 17 for SQL Server]Datetime field overflow. 
    Fractional second precision exceeds the scale specified in the parameter binding.

3 个答案:

答案 0 :(得分:3)

您可以这样舍入到第二个:

PwdLastSetSecond = CDate(Int(PwdLastSet * 86400) / 86400)

答案 1 :(得分:1)

Access中删除时间部分的正确功能是:

DateValue(“日期/时间”表达式)

因此,您得到:

dte = DateValue(CDate(“ 2018-12-24 15:16:17”))

或DateValue(无论日期时间表达式如何)

Access中删除时间部分的正确功能是:

TimeValue(“日期/时间”表达式)

因此,您得到:

dte = TimeValue(CDate(“ 2018-12-24 15:16:17”))

或TimeValue(无论日期/时间表达式如何)

如果您需要将时间部分保存或剥离为单独的值,请执行以下操作:

dtMyTime = TimeValue((CDate(“ 2018-12-24 15:16:17”))

但是,您的问题并未删除日期或时间。

格式中没有“ .ms”这样的东西。

这将给您一个月+秒的时间。

如果你仔细看:

2018-12-24 15:16:17.1217

在上面,te 1217是第12个月零17秒。

格式中没有“ ms”这样的东西。所以这就是为什么您看到溢出的原因

因此您不能使用“ .ms”。

您只能在Access中获得秒数。

只需使用标准格式命令。如果要去除“额外”时间:

  Set rst = CurrentDb.OpenRecordset("dbo_TimeTest2", dbOpenDynaset, dbSeeChanges)

  rst.Edit
  rst!StartTimeD = Format(rst!StartTimeD, "MM-DD-YYYY hh:nn:ss")
  rst.Update

危险危险将罗宾逊。 Access不使用或不支持格式中的“ ms”。

仅在您获得的现有日期/时间上使用上述“格式”,就会在几秒钟后拉出并扔掉多余的值。

答案 2 :(得分:0)

我想出了

dte = CDate(Int(dte) + TimeSerial(Hour(dte), Minute(dte), Second(dte)))

但是那很笨拙。 :(