How to calculate the time lapsed between two dates & times?

The exercise records the date and time a user logs onto a program, and at a later time logs off. The exercise is to measure the time lapsed.
The lapsed time may extend over multiple days, and needs to return days, hours and minutes. Any assistance or direction would be appreciated.

image

I haven’t tested this at all, but something like this seems like what you’re looking for.

TIME:Tick   EQUATE(  1)
TIME:Second EQUATE(100 * TIME:Tick)
TIME:Minute EQUATE( 60 * TIME:Second)
TIME:Hour   EQUATE( 60 * TIME:Minute)
TIME:Day    EQUATE( 24 * TIME:Hour  )

Dates.Span PROCEDURE(LONG xDateA, LONG xTimeA, LONG xDateB, LONG xTimeB, *LONG xOutSpanDays, *LONG xOutSpanTime)
FirstDate  LONG,AUTO 
FirstTime  LONG,AUTO 
SecondDate LONG,AUTO 
SecondTime LONG,AUTO 

    CODE 
    IF (xDateA < xDateB) OR (xDateA = xDateB AND xTimeA < xTimeB)
       FirstDate  = xDateA 
       FirstTime  = xTimeA 
       SecondDate = xDateB
       SecondTime = xTimeB
    ELSE 
       FirstDate  = xDateB 
       FirstTime  = xTimeB 
       SecondDate = xDateA
       SecondTime = xTimeA
    END 

    xOutSpanDays = SecondDate - FirstDate 

    IF FirstTime <= SecondTime 
       xOutSpanTime = SecondTime - FirstTime 
    ELSE 
       xOutSpanDays -= 1
       xOutSpanTime  =  FirstTime - ( SecondTime - TIME:Day )
    END
2 Likes

You have the Duration class that was done as part of a series of Clarion Live Webinars.

Open the Clarion Live Search and type Duration. Part 1 was #491 on Dec 7 2018, Part 2 was #495 on Jan 4 2019, Part 3 was #497 on Jan 18.

1 Like

You should read the help on Clarion Standard Date so you understand a Date in a LONG is stored as the number of Days since 12/28/1800. To get Days between dates you can simply subtract the 2 dates. It harder to use human understandable forms for Day, Month, Year. For that use FORMAT(, @d#) or functions Day(), Month(), Year(), Date().

Also read about Clarion Standard Time so you understand a Time in a LONG is stored as the number of Hundredths of Seconds since midnight … Plus 1 … that +1 is important.

TimeHMS  PROCEDURE(SHORT H, SHORT M, SHORT S=0, SHORT Hundredths=0)!,LONG 
!This allows out of range HMS values, e.g. you can pass 90 minutes. This can produce an invalid time beyond 23:59:59. 
    CODE
    RETURN (H * 60*60*100) + |
           (M *    60*100) + |
           (S *       100) + |
           Hundredths + 1

The DATE and TIME types are different with the Internal Format as YYYYMMDD and HHMMSShh. Anytime they are used in code they are converted to Standard versions i.e. YMD becomes Days since 12/28/1800.

These can be used in code like below to split a DATE or TIME into parts. For dates you have functions for this. Time does not have these so this type of function can be used, or FORMAT(,@T05) that’s HHMMSS.

DateSplit        PROCEDURE(LONG Date2Split, *? OutMonth, *? OutDay, *? OutYear)
!==============================================================================
DateSplit PROCEDURE(LONG D, *? OutMonth, *? OutDay, *? OutYear)
!This is much faster than calling MONTH() DAY() YEAR()
D1 DATE
DG GROUP, OVER(D1)
D BYTE
M BYTE
Y USHORT
  END
    CODE
    D1=D
    OutMonth=DG.M
    OutDay=DG.D
    OutYear=DG.Y
    RETURN
!--------------------------------------------------------------------

TimeSplit PROCEDURE(LONG T, *? OutHour, *? OutMin, <*? OutSec>, <*? OutHund>)
!This is faster than using HOUR() MINUTE() SECOND()
T1 TIME
TG GROUP, OVER(T1)
F BYTE
S BYTE
M BYTE
H BYTE
  END
    CODE
    T1=T
    OutHour=TG.H
    OutMin =TG.M
    IF ~OMITTED(OutSec) THEN OutSec =TG.S.
    IF ~OMITTED(OutHund) THEN OutHund=TG.F.
    RETURN

Many thanks for your detailed response.

Outlook-1484646882.png

Likely irrelevant and late, but I do not see it explicitly stated that topspeed files are being used. For SQL users, calculating an interval with Clarion code is probably not necessary.

Here is something I use on signing out of a time clock. It’s a bit different and doesn’t care much about seconds.

First when clicking the signout button:
HOU:SIGNOUT=clock()
HOU:OUTDATE=today()
do figmins
HOU:TOTAL_HRS=(minutes * 6000) + 1

DISPLAY

figmins routine
set:round_time=0
hou:signin=deformat(format(hou:signin,@t3),@t3)
hou:signout=deformat(format(hou:signout,@t3),@t3)

if hou:outdate-hou:indate > 0

  !**** get time for first day
  td$ = 8640000 - hou:signin  !8640000 = # of 100ths of a sec in one day
  minutes = round(td$/6000,1) !*** num of minutes

  !**** get time for days inbetween day 0 and last day
  if hou:outdate - hou:indate > 1
    minutes = minutes + (((hou:outdate-hou:indate)-1)*1440)
  .

  !**** get time for last day
  minutes+=round(hou:signout/6000,1)

else
  !**** if the days are the same
  minutes = round((hou:signout - hou:signin) / 6000,1) 
  minutes = round(minutes,1)
.

!***** round to nearest minutes here ***
if set:round_time>0
  if minutes => SET:ROUND_TIME
    rem$ = (minutes/set:round_time) - int(minutes/SET:ROUND_TIME) !remainder of minutes
    if rem$ >= .5
      minutes = (int(minutes/SET:ROUND_TIME) * SET:ROUND_TIME) + SET:ROUND_TIME  !round up
    else
      minutes = (int(minutes/SET:ROUND_TIME) * SET:ROUND_TIME)  !round down
    .
  else
    minutes=SET:ROUND_TIME !if less then the round time is equal to the round time
  .
.
exit

set:round_time is a local byte variable and I think its to round to the nearest 5 minutes or 15 minutes or whatever you change it to. Here I think it’s just a zero.

Hope that helps someone.