Как убрать доли секунд из переменной Date? - PullRequest
0 голосов
/ 10 декабря 2018

Фон:

Я читаю атрибут pwdLastSet из Active Directory и хочу сохранить его в столбце DATETIME2(0) в таблице SQL Server.Я не хочу хранить доли секунд.

Это 8-байтовое целое число, выраженное с шагом 100 наносекунд с 12:00 утра, 1 января 1601 года. Я использую эту функцию чтобы преобразовать его в переменную Date.

Это продолжало завершаться ошибкой с ODBC-call failed, и мне потребовалось довольно много времени, чтобы понять, что дополнительная точность, возвращаемая этой функцией, вызвала ошибку.

Вопрос:

Каков наилучший способ удалить доли секунд из переменной Date?


Как воспроизвести:

Я использую SQL Server2008 R2 и Access 2010.
В 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

Свяжите эту таблицу с Access, используя драйвер ODBC для собственного клиента или текущий Драйвер Microsoft ODBC 17 для SQL Server .Драйвер по умолчанию для 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 голосов
/ 10 декабря 2018

Вы можете округлить до секунды следующим образом:

PwdLastSetSecond = CDate(Int(PwdLastSet * 86400) / 86400)
0 голосов
/ 10 декабря 2018

Правильная функция в 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

В приведенном выше коде 1217 означает 12-й месяц, а 17 сек.nds ..

НЕТ ТАКОГО «мс» для формата.Вот почему вы видите переполнение .

, поэтому вы НЕ МОЖЕТЕ ИСПОЛЬЗОВАТЬ «.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» в формате.

Простое использование указанного выше «формата» для существующей даты / времени, которое вы получите, вытащит и выбросит дополнительные значения через секунды.

0 голосов
/ 10 декабря 2018

Я придумал

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

но это довольно неуклюже.(

...