qbasic - timer

HomePage | Optical Illusions | War Stories | QBasic | Dads Navy Days | Bristol | Bristol, USA | Bristol, Canada | Terre Haute | Miscellany | Web Stuff | About Ray | Site Map | Site Search | Messages | Credits | Links | Web Rings

QBasic | Errors | 40lb Weight | Bits | Chance | Colours | Dates | Delays | File Dialog | Files | Input | Matching | Menus | Mouse | Numbers | SeqNo | SIRDS | Sorts | Text | Timer | DLoads

Visual Basic has a percent flood fill feature which is useful for displaying the percentage complete of a process. I thought it would be nice to do my own in QBasic. It's not so pretty but does the job.

This is a slightly more complicated program, here's the code for it :

DIM Count AS INTEGER     'Used for loops, general numeric variable
DIM Hrs AS INTEGER       'Hold hours
DIM Mins AS INTEGER      ' Holds minutes
DIM PerCent AS INTEGER   'Calculates percentage done 
DIM Counter AS LONG      'Used for loops, general numeric variable
DIM Elapsed AS LONG      'Used to calculate times
DIM Num AS LONG          'General numeric variable
DIM EndTimer AS LONG     'Holds the end time
DIM EstTime AS LONG      'Used to claculate times
DIM secs AS LONG         'Holds seconds
DIM StrtTimer AS LONG    'Holds the start time
DIM PerCntdone AS STRING 'Used to calculate % done and position on screen

CLS

PRINT "Busy.Bas Ray Thomas, September 1998"
PRINT
PRINT "This small program can work out and display a percent done bar"
PRINT "a la Visual Basic (but not so pretty)."
PRINT
PRINT
PRINT "Press any key to continue ..."

DO
LOOP UNTIL INKEY$ <> ""

Num = 307      'A made up number, could be the number of records to process

CLS
PRINT "Working, please wait ..."
PRINT
PRINT
PRINT CHR$(201); STRING$(50, CHR$(205)); CHR$(187)
PRINT CHR$(186); SPACE$(50); CHR$(186)
PRINT CHR$(200); STRING$(50, CHR$(205)); CHR$(188)

StrtTime = TIMER
PRINT
PRINT "Routine started on :", " "; MID$(DATE$, 4, 2); "/"; LEFT$(DATE$, 2); "/";
PRINT RIGHT$(DATE$,2); " at "; TIME$

FOR Count = 1 TO Num
	Hrs = 0
	Mins = 0
	secs = 0

	FOR Counter = 1 TO 100000   'This loop merely to act as a delay
	NEXT Counter                'but could be processing records etc

	EndTime = TIMER
	Elapsed = EndTime - StrtTime 	'gives the elapsed time in seconds
	secs = Elapsed

	IF Elapsed >= 60 THEN
		Mins = FIX(Elapsed / 60)
		secs = Elapsed - (60 * Mins)
	END IF

	IF Mins >= 60 THEN
		Hrs = FIX(Mins / 60)
		Mins = Mins - (60 * Hrs)
	END IF

	LOCATE 9, 1
	PRINT "Elapsed time :", Hrs; "Hours"; Mins;"Minutes"; FIX(secs); "Seconds "

	Hrs = 0
	Mins = 0
	secs = 0

	EstTimes = (Elapsed / Count) * (Num - Count)
	secs = EstTimes

	IF EstTimes >= 60 THEN
		Mins = FIX(EstTimes / 60)
		secs = EstTimes - (60 * Mins)
	END IF

	IF Mins >= 60 THEN
		Hrs = FIX(Mins / 60)
		Mins = Mins - (60 * Hrs)
	END IF


	LOCATE 10, 1
	PRINT "Estimated time to go :", Hrs; "Hours";Mins; "Minutes"; FIX(secs); "Seconds "
	PerCent = (Count / Num) * 100
	PerCntdone$ = STR$(PerCent) + "% complete "
	LOCATE 5, 2
	PRINT STRING$(Count / (Num / 50), CHR$(177));
	LOCATE 4, 20
	PRINT PerCntdone$;
NEXT Count

LOCATE 1, 1
PRINT "Finished "
LOCATE 11, 1
PRINT "Routine finished on :", " "; MID$(DATE$,4, 2); "/"; LEFT$(DATE$, 2); "/"; 
PRINT RIGHT$(DATE$,2); " at "; TIME$
PRINT "Number of iterations :", Num

END

During May 2000, I had a very interesting email saying that if used near midnight then the above code will not work correctly. On investigation, I realised why, the time elapsed is worked out by using the TIMER function which returns the number of seconds elapsed since midnight.

Suppose the program was started at 11pm and ran till 2am. The line StrtTime = TIMER would make StrtTime equal to 82800 (the number of seconds in 23 hours). The line EndTime = TIMER would make EndTime equal to 7200 (the number of seconds in 2 hours). When working out the number of seconds elapsed, Elapsed = EndTime - StrtTime, would make Elapsed equal to -75600, which isn't quite what we want.

A solution would be to replace Elapsed = EndTime - StrtTime with :-

IF  EndTime  <  StrtTime  THEN  Elapsed   =   86400  -  StrtTime  + EndTime
ELSE  Elapsed  = EndTime - StrtTime

86400 is the number of seconds in 24 hours.

Of course this only works if the program is running for less than one day, for longer processes additional problems are introduced. The programmer must check to see how many days have passed since the process was started. The DATE$ command can be used and then a routine written to do the maths of taking one date away from another, but because you have to take into account the differing number of days in a month a simpler solution would be to check the TIMER periodically, if the reading is less than the reading before then another variable, which would count the days needs to be incremented.

Just before the process to be timed starts insert :-

LastTime = TIMER

During the process to be timed (remember that this must be done before 24 hours have elapsed) insert:-

ThisTime = TIMER
IF ThisTime < LastTime THEN
     DayCount = DayCount + 1
     LastTime = ThisTime
END IF

The total time elapsed can now be calculated as :-

EndTime  =  TIMER
Elapsed  =  (DayCount  *  86400)  +  EndTime  - StrtTime

The program snippets above may need editing, if the EndTime is very close to midnight then the DayCount counter may not be incremented properly. An extra line

IF EndTime < StrtTime THEN DayCount = DayCount + 1

may be needed to be added between the last two program lines.

During the email correspondence I wrote a program to investigate what happens to the system clock, TIMER and ON TIMER functions. The program changes the system time so it is best not to stop it from finishing itself, it will reset the system clock to the correct time when it finishes. As the clock passes midnight the system date will also change. The date is also reset near the end of the program.

Using the ON TIMER(x) GOSUB function and a simple counter loop. As in the program above there is a problem with the TIMER function as it changes from 86400 to 0 at midnight. The ON TIMER function however still works as it should. As in the above program the time elapsed calculation is corrected by the addition of 86400 to the calculation.

In November 2003, I received an email from Jonathan Simpson saying that in QBasic 7.1 the following code can be used

DIM a AS LONG, b AS LONG, days AS INTEGER
a = INT(NOW)
DO UNTIL something
    b = INT(NOW)
    IF b > a THEN days = days + 1: a = INT(NOW)
    LOCATE 1, 1: PRINT days, NOW
LOOP

Unfortunately QBasic v1.1 hasn't this facility.

'Midnight        Ray Thomas      May 2000

'A program to investigate what happens to the system clock and
'TIMER functions at midnight

CLS
StartTime$ = TIME$              'Get the time the program was started
StartDate$ = DATE$              'Get the present  system date
TIME$ = "23:59:55"              'Set the system time to just before midnight
ProgStart = TIMER               'Get the number of seconds past midnight
Start = TIMER
ON TIMER(1) GOSUB TimeUp        'Set up the timer interupt
TIMER ON                        'Start the timer interupt
FOR Count = 1 TO 1000000        'A do nothing loop
NEXT Count
TIMER OFF                       'Stop the timer interupt
PRINT "Count ended"; Count
PRINT
PRINT "Press any key to reset the system clock ..."
DO
LOOP UNTIL INKEY$ <> ""
GOSUB ResetTime
END

TimeUp:
'*** Do whatever you want to do after the timer interupts

Finish = TIMER
PRINT
PRINT "The time is now: "; TIME$

'*** Stop the program to read what happens to the counters at midnight

IF TIME$ = "00:00:02" THEN
        TIMER OFF
        PRINT "press any key to continue ..."
        DO
        LOOP UNTIL INKEY$ <> ""
        TIMER ON
END IF

PRINT "The Count is now at:"; Count
PRINT Finish - Start; "seconds elapsed"

'*** This is the part that checks for what happens at midnight
'*** it is here that the start time is greater than the finish time

IF Start > Finish THEN
        PRINT "Amended time elapsed"; 86400 - Start + Finish
        PRINT CINT(86400 - Start + Finish); "rounded amended second(s) elapsed"
ELSE PRINT CINT(Finish - Start); "rounded second(s) elapsed"
END IF
PRINT "The end time is"; Finish
PRINT "The start time is"; Start
Start = TIMER
RETURN

ResetTime:
'*** Work out the total time elapsed
'*** and reset the system date and time

PRINT
PRINT "The date when the program was started was "; StartDate$
PRINT
PRINT "The time when the program was started was "; StartTime$
PRINT
PRINT "The date has changed to "; DATE$
PRINT
PRINT "Resetting the date to "; StartDate$
PRINT
DATE$ = StartDate$
Finish = TIMER
PRINT "The program was running for"; CINT(86400 - ProgStart + Finish); "seconds"
Hours = VAL(LEFT$(StartTime$, 2))
Mins = VAL(MID$(StartTime$, 4, 2))
Secs = VAL(RIGHT$(StartTime$, 2))
Finish = TIMER
Secs = Secs + CINT(86400 - ProgStart + Finish)
IF Secs > 60 THEN
        Mins = Mins + INT(Secs / 60)
        Secs = Secs MOD 60
END IF
IF Mins > 60 THEN
        Hours = Hours + INT(Mins / 60)
        Mins = Mins MOD 60
END IF
NewTime$ = LTRIM$(STR$(Hours)) + ":" + LTRIM$(STR$(Mins)) + ":" + LTRIM$(STR$(Secs))
TIME$ = NewTime$
PRINT
PRINT "The time has been restored to "; TIME$
RETURN

QBasic | Errors | 40lb Weight | Bits | Chance | Colours | Dates | Delays | File Dialog | Files | Input | Matching | Menus | Mouse | Numbers | SeqNo | SIRDS | Sorts | Text | Timer | DLoads

HomePage | Optical Illusions | War Stories | QBasic | Dads Navy Days | Bristol | Bristol, USA | Bristol, Canada | Terre Haute | Miscellany | Web Stuff | About Ray | Site Map | Site Search | Messages | Credits | Links | Web Rings

This page last updated 23rd November 2003