简体   繁体   中英

Interval between two dates in VBA

Start time "08:58" , end time "17:37" . Expected result is 8.39 meaning elapsed time of 8 hours and 39 minutes. I tried this:

Function UDF_datediff(d1 As Date, d2 As Date) As Double
    Dim hours As Integer
    Dim minutes As Integer

    hours = DateDiff("h", d1, d2)
    minutes = (DateDiff("n", d1, d2) Mod 60)

    UDF_datediff = hours + minutes / 100
End Function

But it calculates wrong results for hours. Surprisingly! Would you share any suggestion to calculate expected results?

Try this:

Sub Test()
    Dim minutes As Long
    Dim d1 As Date, d2 As Date
    d1 = "2018-01-01 08:58:00"
    d2 = "2018-01-01 17:37:00"
    minutes = DateDiff("n", d1, d2)
    ' Will print 8.39
    MsgBox Int(minutes / 60) & "." & minutes Mod 60
End Sub
Function UDF_datediff(d1 As Date, d2 As Date) As Double
    Dim difference AS Double
    difference = d2 - d1
    UDF_datediff = Sgn(difference) * CDbl(Format(difference , "hh.mm"))
End Function

In your example, d2 - d1 is a DateTime of 1899-12-30 08:37:00 - Format this as Hours (2 digits), decimal point, Minutes (2 digits), then convert to a double and correct the sign.

Try

Sub test()
    Dim d1 As Date, d2 As Date
    Dim m As Double

    d1 = TimeValue("08:58")
    d2 = TimeValue("17:37")
    m = UDF_datediff(d1, d2)
    MsgBox m
    MsgBox Format(m / 24, "hh:mm")
End Sub

UDF

Function UDF_datediff(d1 As Date, d2 As Date) As Double

    UDF_datediff = (d2 - d1) * 24
End Function

DateDiff is actually not quite needed. You may use a simple "minus" to see what's going on:

Sub TestMe() 

    With Worksheets(1)
        Dim d1 As Date: d1 = 0.373611111111111 '08:58:00
        Dim d2 As Date: d2 = 0.734027777777778 '17:37:00
    End With
    Debug.Print UdfDatediff(d1, d2)            '08:39:00

End Sub

Function UdfDatediff(d1 As Date, d2 As Date) As Date

    UdfDatediff = Abs(d1 - d2)

End Function

The date in VBA is presented as a double number. Thus, if you write 0.373611111111111 and format it to in Date in VBA you would get:

?CDate(0.373611111111111)
08:58:00

The double values above are obtained through writing the following in the Immediate Window Ctrl + G :

?CDbl(TimeSerial(8,58,0))
 0,373611111111111 

In Excel, the date is also presented as a double number, but for the first two months of the year 1900 it is a bit deviating from the date in VBA (See the question of BillG here ).

alternatively - given that times are stored as decimal fractions of a day

 Function UDF_datediff(d1 As Date, d2 As Date) As Double
    d2 = d2-int(d2) 'remove date portion
    d1= d1 - int(d1)
    UDF_datediff = (d2-d1)*24
  End Function

The general answer is this:

      Format(CDate(d2-d1),"h:m")

For your Start and End times in particular, this expression will produce the "8:39" result.

If you need to extract hours and minutes from this, you can do this:

Dim sDuration as String
Dim iCol as Long
Dim sH as String
Dim sM as String
Dim iH as Long
Dim iM as Long

sDuration = Format(CDate(d2-d1),"h:m") ' the "8:39" in your case
iCol =InStr(sDuration, ":") 
sH = Left(sDuration, iCol - 1)
sM = Mid(sDuration, iCol + 1, 2) ' length of 2 or any longer
iH = CInt(sH)
iM = CInt(sM)

You can always work with the "numbers", converting decimals, multiplying by 24 and by 60, rounding... as in

iH = Int(CDate(d2-d1)*24) ' to get the hours

etc. (it's a bit more complicated with Minutes)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM