Time calculations

Technical support and scripting issues

Moderators: Dorian (MJT support), JRL

Post Reply
User avatar
Phil Pendlebury
Automation Wizard
Posts: 543
Joined: Tue Jan 16, 2007 9:00 am
Contact:

Time calculations

Post by Phil Pendlebury » Fri Feb 12, 2010 3:54 pm

Greetings,

I though this may be an interesting discussion. I have searched around and found a few bits but nothing in concrete.

I recently wrote a script that takes a number of frames (frames are a fraction of a second - of varying values depending on frame "rate" used in the music and film industry) and converts it to hours minutes and seconds (and frames).

Also vice versa. You enter Hours Minutes Seconds Frames and it will convert to the total number of frames. (that part is easy - very simple math).

I have also done similar scripts for working out delay times / BPM and other things (music related)

The time calculations always cause me a bit of trouble.

What I end up doing is looping through a script that takes the total seconds and deducts 60 while adding 1 to the minute counter etc. Or dividing seconds by 3600 which give you hours etc.

I have used VBScript to calculate time differences but I can't find anything relevant to calculate actual time mathematics.

Let me give you a really simple example:

Let's say that I am giving you a random number between 1 and 100,000
That is a number of seconds.

How would you guys work out how many Hours, Minutes and Seconds that number will contain - without using the two methods I mentioned above?

Is it possible to find maybe a VB Script command that will simply give you the answer.

For example ( I know my code is wrong but just as an example)

Let>seconds = 123456
VBEvalTimeFromSeconds - (seconds) result_variable
MDL>%seconds% seconds = %result_variable%

Message would read: 123456 seconds = 34:17:36

(or similar).

As I said, my time scripts are working well already and I am sure that I will always have to do my own calculations on frame rates but I was just interested to see what you guys thought.

nb: You can download the complied Frame Rate Calc from here:

http://www.box.net/shared/xujuimo8z6

Cheers,

:-)

PS. This may be better in the discussion section. Whatever you moderators think is fine with me. :-)
Phil Pendlebury - Linktree

gdyvig
Automation Wizard
Posts: 447
Joined: Fri Jun 27, 2008 7:57 pm
Location: Seattle, WA

Post by gdyvig » Fri Feb 12, 2010 5:45 pm

Hi Phil,

It can be calculated very simply using Macro Schedulers DIV and MOD arithimetic operators in a complex expression.

Code: Select all

Input>iElapsedSeconds,Enter integer number of elapsed seconds,0
Let>iInputSeconds=%iElapsedSeconds%
Let>iHours={%iElapsedSeconds% div 3600}
Let>iElapsedSeconds={%iElapsedSeconds% mod 3600}
Let>iMinutes={%iElapsedSeconds% div 60}
Let>iSeconds={%iElapsedSeconds% mod 60}
MDL>%iInputSeconds%=%iHours%:%iMinutes%:%iSeconds%
Gale

User avatar
Phil Pendlebury
Automation Wizard
Posts: 543
Joined: Tue Jan 16, 2007 9:00 am
Contact:

Post by Phil Pendlebury » Fri Feb 12, 2010 7:20 pm

Thanks Gale that's a great solution.

I didn't think of div and mod.... Which probably sounds daft but that's just me.

:-)
Phil Pendlebury - Linktree

User avatar
Phil Pendlebury
Automation Wizard
Posts: 543
Joined: Tue Jan 16, 2007 9:00 am
Contact:

Post by Phil Pendlebury » Fri Feb 12, 2010 7:36 pm

However...

It seems that div and mod are incompatible with float numbers... Let me explain:

Frame Rate is a division of seconds. It can be 24, 25, 29.97, 30 or even some other numbers.

So take 123456 frames for example this actually equals 4938.24 seconds.

When that amount is used to start the hours minutes seconds calculation - the script throws up an error because it is a float number.
Phil Pendlebury - Linktree

User avatar
JRL
Automation Wizard
Posts: 3526
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Fri Feb 12, 2010 10:36 pm

When that amount (4938.24 seconds) is used to start the hours minutes seconds calculation - the script throws up an error because it is a float number.
That's why the "round" function was invented.

Modified Gales script a bit by adding "round" to the first Let> line. Also reversed the "iInputSeconds" and the "iElapsedSeconds" variables in the first two lines. BTW, nice, well conceived script Gale!

And if you think you need that fraction of a second added on the result time, that could easily be accomplished by stripping the characters to the right of the decimal point using the Separate> function. Then pasting those decimal characters on the end so the result would look like:
HH:MM:SS.SSS

Code: Select all

Input>iInputSeconds,Enter integer number of elapsed seconds,0

Let>iElapsedSeconds={round(%iInputSeconds%)}
Let>iHours={%iElapsedSeconds% div 3600}
Let>iElapsedSeconds={%iElapsedSeconds% mod 3600}
Let>iMinutes={%iElapsedSeconds% div 60}
Let>iSeconds={%iElapsedSeconds% mod 60}
MDL>%iInputSeconds%=%iHours%:%iMinutes%:%iSeconds%

User avatar
Phil Pendlebury
Automation Wizard
Posts: 543
Joined: Tue Jan 16, 2007 9:00 am
Contact:

Post by Phil Pendlebury » Sat Feb 13, 2010 2:06 pm

Hi again guys.

OK well this is ending up pretty similar to my original script.

If you look at the file I linked to - you would see that the fraction of seconds is required and indeed essential to the calculations.

Also there is the issues with decimal place being different for different languages. So I used the old trick:

Code: Select all

Let>num=0.1
LibFunc>kernel32,GetNumberFormatA,r,0,0,str:num,0,buf,255
MidStr>r_5,2,1,DecimalPlaceHolder

Code: Select all


StringReplace>drate,DecimalPlaceHolder,.,drate
At various points throughout my script. (Many of my users are French - who use a comma as decimal point).

I then ended up using Trunc and Frac to do my final calculations.

So in fact this code is now not much more simple than what I already have. Although it is neater that's for sure.

I really was hoping that there would be some kind of VB Script command to do this which would keep the result in a float number and not require the messing with decimal place holder etc.

Thanks anyway, interesting to see how you expert guys would deal with this.

Please feel free to have a look at the linked file (you will see that it works in ANY language) or if anyone is interested enough I will post the full script here.

:)
Phil Pendlebury - Linktree

User avatar
JRL
Automation Wizard
Posts: 3526
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Sun Feb 14, 2010 7:10 pm

Ok Phil... So here's the best I could come up with for a vbscript solution. Also used Separate to break up the decimals even if using a comma. I would guess that much of this could be improved by RegEx but I've yet to attempt RegEx.

What this does is add the seconds quantity onto microsoft's beginning of time giving a result in a date/time format. Then it uses "datediff" between the origin of time and date/time formated "dateadd" result to get the number of hours. It then uses Separate to strip off unwanted garbage. Then we rebuild the string using the hours from datediff.

Step through this in the editor and it will be much clearer than I can explain. In any case this is probably not the easiest solution to your challenge. But it does use VBScript

Code: Select all

VBSTART
VBEND
Input>number,Enter number of seconds,1234568,1234
Let>comma=,
Separate>number,comma,cTest
StringReplace>number,comma,.,number
Separate>number,.,nPart


VBEval>DateAdd("s", %nPart_1%, "00:00:00"),res
VBEval>DateDiff("h", #00:00:00#, #%res%#),hourres
Separate>res,:,tItem
Separate>tItem_3, ,seconds


If>nPart_count=1
  MDL>%hourres%:%tItem_2%:%seconds_1%
Else
  If>%cTest_count%=2
   MDL>%hourres%:%tItem_2%:%seconds_1%%comma%%nPart_2%
  Else
   MDL>%hourres%:%tItem_2%:%seconds_1%.%nPart_2%
  EndIf
EndIf

User avatar
Phil Pendlebury
Automation Wizard
Posts: 543
Joined: Tue Jan 16, 2007 9:00 am
Contact:

Post by Phil Pendlebury » Sun Feb 14, 2010 8:06 pm

Thanks JRL. That is very neatly and elegantly done compared to my original rather ugly solution.

Don't forget this wasn't a pleas for help but more a topic of interest and as usual, I have learned a lot from you guys thank you.

Here's my original script btw in case you are interested:

Code: Select all

Let>RP_ADMIN=1
Let>APP_TITLE=Frame Calculator
Let>MSG_STAYONTOP=1
Let>MSG_CENTERED=1
Let>MSG_WIDTH=360
Let>MSG_HEIGHT=200
Let>WF_TYPE=1
Let>VAREXPLICIT=0
Let>CF_OVERWRITE=1
Let>reg_pattern=[1 or more digits]:[1 or more digits]:[1 or more digits].[1 or more digits]
Let>reg_pattern_text=[letter]

VBSTART
''
VBEND
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
//Determine the decimal placeholder
Let>num=0.1
LibFunc>kernel32,GetNumberFormatA,r,0,0,str:num,0,buf,255
MidStr>r_5,2,1,DecimalPlaceHolder
///////////////////////////////////////////////////////////////////////
Dialog>Dialog1
   Caption=FR Calc
   Width=240
   Height=178
   Top=CENTER
   Left=CENTER
   Max=0
   Min=0
   Close=0
   Resize=0
   Edit=msEdit2,72,40,73,25
   Edit=msEdit1,8,70,137,0
   Edit=msEdit3,8,100,137,0:0:0.0
   Label=Frame Rate Calc by Phil Pendlebury,10,8,true
   Label=Frame Rate:,10,42,true
   Button=Calc Frames,152,69,74,23,4,,Calculate Frames from a Time entry and add Frames to clipboard
   Button=Calc Time,152,99,74,23,3,,Calculate Time from number of frames and add Time to clipboard
   Button=Quit,152,39,74,23,6,,Bye Bye!
   MainMenu=Menu,About(30),Help(40),Developers(50),MEAP(60),Quit(6)
EndDialog>Dialog1
///////////////////////////////////////////////////////////////////////
Label>ShowD
Show>Dialog1
Label>DialogLoop
  GetDialogAction>Dialog1,res
  IF>res=3,calctime
  IF>res=4,calcframes
  IF>res=6,exit
  IF>res=30
    MDL>Frame Rate Calculator by Phil Pendlebury%CRLF%%CRLF%Version 2.01 - 16 February 2010
    RDA>Dialog1
  ENDIF
  IF>res=40
    MDL>ALWAYS Enter a Frame Rate%CRLF%%CRLF%Enter TOT FRAMES and hit Calc Time to get the time from the number of frames.%CRLF%%CRLF%Enter H:M:S.F and hit Calc Frames to get total frames from that time.
    RDA>Dialog1
  ENDIF
  IF>res=50
    MDL>Phil Pendlebury%CRLF%%CRLF%http://www.pendlebury.biz/%CRLF%%CRLF%Thanks to: Fredo, Panos, Bo, Neil
    RDA>Dialog1
  ENDIF
  IF>res=60
    ExecuteFile>http://www.meap.biz/
    RDA>Dialog1
  ENDIF
  //
  Let>dtotal=%Dialog1.msEdit1%
  Let>drate=%Dialog1.msEdit2%
  Let>dtime=%Dialog1.msEdit3%
  Let>doingtime=3

  //
  Wait>0.001
GOTO>DialogLoop
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
SRT>calctime
  Let>doingtime=1
  GOSUB>isnumber
  // from frames
  StringReplace>drate,DecimalPlaceHolder,.,drate
  Let>allframes=%dtotal%
  GOSUB>gettimefromsecs
  Let>all_time=%chours%:%cminutes%:%cseconds%.%cframes%
  Let>Dialog1.msEdit3=%all_time%
  PutClipBoard>%all_time%
  RDA>Dialog1
END>calctime
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
SRT>calcframes
  Let>doingtime=2
  GOSUB>sep_time
  GOSUB>isnumber
  // from time
  StringReplace>drate,DecimalPlaceHolder,.,drate
  GOSUB>getsecsfromtime
  Let>Dialog1.msEdit1=%dtotal%
  PutClipBoard>%dtotal%
  RDA>Dialog1
END>calcframes
///////////////////////////////////////////////////////////////////////

Label>exit

///////////////////////////////////////////////////////////////////////
SRT>gettimefromsecs

Let>allseconds=allframes/drate
StringReplace>%allseconds%,DecimalPlaceHolder,.,allseconds
////////////////////////////////
let>chours=0
Label>get_hours
IF>allseconds>3599
  let>chours=chours+1
  let>allseconds=allseconds-3600
  StringReplace>%allseconds%,DecimalPlaceHolder,.,allseconds
ENDIF
IF>%allseconds%<3600
  GOTO>skip_hours
ENDIF
GOTO>get_hours
Label>skip_hours
////////////////////////////////
let>cminutes=0
Label>get_minutes
IF>allseconds>59
  let>cminutes=cminutes+1
  let>allseconds=allseconds-60
  StringReplace>%allseconds%,DecimalPlaceHolder,.,allseconds
ENDIF
IF>%allseconds%<60
  GOTO>skipminutes
ENDIF
GOTO>get_minutes
Label>skipminutes
////////////////////////////////
Let>cseconds={Trunc(%allseconds%)}
Let>fracseconds={Frac(%allseconds%)}

StringReplace>%fracseconds%,DecimalPlaceHolder,.,fracseconds
Let>fracframes=fracseconds*drate
StringReplace>%fracframes%,DecimalPlaceHolder,.,fracframes
Let>cframes=%fracframes%
// Round to 6 DP

VBEval>Round(%cframes%,10),cframes

// MidStr>%cframes%,1,10,cframes
////////////////////////////////
// MDL> HOUR: %chours% MIN: %cminutes% SEC: %cseconds% FR: %cframes%
END>gettimefromsecs
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
SRT>getsecsfromtime
  //
  Let>fhours=%dhours%*60
  Let>fhours=%fhours%*60
  Let>fhours=%fhours%*%drate%
  //
  Let>fminutes=%dminutes%*60
  Let>fminutes=%fminutes%*%drate%
  //
  Let>fseconds=%dseconds%*%drate%
  //
  Let>dtotal=%fhours%+%fminutes%
  Let>dtotal=%dtotal%+%fseconds%
  Let>dtotal=%dtotal%+%dframes%
  //
  // MDL>Total Frames: %dtotal%
END>getsecsfromtime
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
SRT>sep_time
// 
Separate>dtime,:,sep_hms
Separate>sep_hms_3,.,sep_frm
Let>dhours=%sep_hms_1%
Let>dminutes=%sep_hms_2%
Let>dseconds=%sep_frm_1%
Let>dframes=%sep_frm_2%
END>sep_time
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
SRT>isnumber
   IF>%drate%>0
     Let>check_drate=%drate%/%drate%
     IF>check_drate<>1
       Let>error=FRAME RATE
       GOSUB>reset
     ENDIF
   ELSE
     IF>%drate%=0
        MDL>Frame Rate must be something other than Zero!
        RDA>Dialog1
        GOTO>DialogLoop
     ENDIF
   ENDIF
   IF>%drate%=
      MDL>Frame Rate must contain a value!
      RDA>Dialog1
      GOTO>DialogLoop
   ENDIF

   IF>doingtime=1
   IF>%dtotal%=
      MDL>Frames must contain a value!
      RDA>Dialog1
      GOTO>DialogLoop
   ENDIF
     IF>%dtotal%>0
       Let>check_dtotal=%dtotal%/%dtotal%
       IF>check_dtotal<>1
         Let>error=FRAMES
         GOSUB>reset
       ENDIF
     ELSE
       MDL>Frames must contain a value greater than Zero!
     ENDIF
   ENDIF


   IF>doingtime=2
   IF>%dtime%=
      MDL>Time must contain a value!
      RDA>Dialog1
      GOTO>DialogLoop
   ENDIF
     IF>%dtime%=0:0:0.0
       MDL>Time must contain a value greater than Zero!
     ENDIF
     IF>%dtime%>0
       RegEx>reg_pattern_text,dtime,1,tmatches,tnum,0
       IF>tnum>0
         MDL>Time Must not contain letters!
         RDA>Dialog1
         GOTO>DialogLoop
       ENDIF
       RegEx>reg_pattern,dtime,1,matches,num,0
       IF>num<1
         MDL>Time Must be in format H:M:S.F (0:0:0.0)
         RDA>Dialog1
         GOTO>DialogLoop
       ENDIF
     ENDIF
   ENDIF
END>isnumber
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
SRT>reset
  MDL>%error% contains a value that isn't a number!
  RDA>Dialog1
  GOTO>DialogLoop
END>reset
///////////////////////////////////////////////////////////////////////
Phil Pendlebury - Linktree

arobin4
Junior Coder
Posts: 33
Joined: Sat Apr 07, 2012 5:41 am

Including Commas in variable Number

Post by arobin4 » Thu May 24, 2012 4:38 am

Hi Forum,
I am interesting in seeing the commas in a number when it is displayed in a dialog or message box. Is there a straightforward approach e.g., a format function?

Here is a snippet of my code:

Random>5000000,r
Let num=100000+r
MessageModal>num

The variable 'num' is displayed without any commas.

Thanks

User avatar
Rain
Automation Wizard
Posts: 550
Joined: Tue Aug 09, 2005 5:02 pm
Contact:

Post by Rain » Thu May 24, 2012 3:00 pm

I hope this helps...

Code: Select all

VBSTART
VBEND
Random>5000000,r
Let>num=100000+r
VBEval>FormatNumber(%num%,0),DisplayNumber
MessageModal>DisplayNumber


arobin4
Junior Coder
Posts: 33
Joined: Sat Apr 07, 2012 5:41 am

Post by arobin4 » Thu May 24, 2012 3:26 pm

Yes Rain, this is exactly what I was looking for. Thank you very much.

Post Reply
cron
Sign up to our newsletter for free automation tips, tricks & discounts