Author Topic: adding/subtracting times  (Read 5533 times)

0 Members and 1 Guest are viewing this topic.

Offline JohnUKresults

  • Newbie
  • Posts: 40
    • View Profile
adding/subtracting times
« on: July 26, 2020, 03:53:07 pm »
Hi

Someone out there must have come across this before.

I need to subtract one time from another, to work out an elspased time.

The times are stored in the format hh:mm:ss.dd so are always the same length (time of day stored to 2 decimal places)

Anyone got some code which can do this?

I'll need to have the result stored in (a) the same format (i.e. to 2 decimal places) and also (b) as a number of seconds rounded up to the next full second (anything after the deimal point rounds up, not just to the nearest second), but I can probably figure that out once I've got the subtraction worked out.

It will save me having to write some convoluted code (as I'm not exactly smart with this stuff)

Many thanks for your time.

John

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: adding/subtracting times
« Reply #1 on: July 26, 2020, 04:31:33 pm »
Steve started with a Timestamp thing and I was interested in checking days and time passage both here:
https://www.qb64.org/forum/index.php?topic=1638.msg108566#msg108566

I got burnt out testing Steve's fixes but this maybe helpful for you @JohnUKresults ? If you limited it to 24 hour period it would be way easier than what we were playing with! ;-))

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: adding/subtracting times
« Reply #2 on: July 26, 2020, 04:46:47 pm »
Here you go, @JohnUKresults
This solution shows using PowerShell. I've not parsed the return string from PowerShell but I'll leave that up to you. Have fun!
P.S. You'll probably need to run PowerShell in Administrator mode and run this below command because the default in Windows 10 is to not allow running of scripts:
Quote
Set-ExecutionPolicy RemoteSigned

Code: QB64: [Select]
  1. startTime$ = "10:20:20.10"
  2. endTime$ = "20:10:30.15"
  3. PS1 = FREEFILE
  4. OPEN "timediff.ps1" FOR OUTPUT AS #PS1
  5. PRINT #PS1, "$StartDate = [datetime]" + CHR$(34) + startTime$ + CHR$(34)
  6. PRINT #PS1, "$EndDate = [datetime]" + CHR$(34) + endTime$ + CHR$(34)
  7. PRINT #PS1, "New-TimeSpan -Start $StartDate -End $EndDate | Out-File -FilePath .\timediff.d -Encoding ASCII"
  8. CLOSE #PS1
  9. SHELL _HIDE "PowerShell .\timediff.ps1"
  10. KILL "timediff.ps1"
  11. DIM timedifference AS STRING
  12. OPEN "timediff.d" FOR BINARY AS #d
  13. IF LOF(d) <> 0 THEN
  14.     timedifference = SPACE$(LOF(d))
  15.     GET #d, , timedifference
  16. KILL "timediff.d"
  17. PRINT timedifference
« Last Edit: July 26, 2020, 04:51:01 pm by SpriggsySpriggs »
Shuwatch!

Offline JohnUKresults

  • Newbie
  • Posts: 40
    • View Profile
Re: adding/subtracting times
« Reply #3 on: July 27, 2020, 04:39:12 am »
Many thanks

I'm trying to keep it within QB64 for various reasons, but I'll certainly have a close look at this

Regards

John

Offline Richard Frost

  • Seasoned Forum Regular
  • Posts: 316
  • Needle nardle noo. - Peter Sellers
    • View Profile
Re: adding/subtracting times
« Reply #4 on: July 27, 2020, 04:45:10 pm »
No array, SUB, or FUNCTION, keeping it simple....

Code: QB64: [Select]
  1. ' math with hh:mm:ss.dd
  2.  
  3. DEFINT A-Z
  4. t1$ = "10:17:12.45"
  5. t2$ = "11:53:52.18"
  6. t$ = t1$: GOSUB woof: f1! = f!
  7. t$ = t2$: GOSUB woof: f2! = f!
  8. f! = f2! - f1!
  9. hh = f! \ 3600
  10. mm = (f! - hh * 3600) \ 60
  11. s! = (f! - hh * 3600 - mm * 60)
  12. s! = INT(s! * 100) / 100
  13. h$ = RIGHT$("0" + LTRIM$(STR$(hh)), 2)
  14. m$ = RIGHT$("0" + LTRIM$(STR$(mm)), 2)
  15. s$ = RIGHT$("0" + LTRIM$(STR$(s!)), 5)
  16.  
  17. p = INSTR(s$, ".")
  18. IF p < 3 THEN s$ = "0" + s$ '               add leading zero to seconds, if needed
  19.  
  20. WHILE LEN(s$) < 5 '                         add trailing zeros to seconds, if needed
  21.     s$ = s$ + "0"
  22.  
  23. PRINT t1$
  24. PRINT t2$
  25. t$ = h$ + ":" + m$ + ":" + s$
  26. PRINT INT(f! + .5)
  27.  
  28. woof:
  29. hh = VAL(MID$(t$, 1, 2))
  30. mm = VAL(MID$(t$, 4, 2))
  31. s! = VAL(MID$(t$, 7, 5))
  32. f! = CDBL(hh) * 60 * 60 + mm * 60 + s!
  33.  
  34.  
« Last Edit: July 27, 2020, 04:59:06 pm by Richard Frost »
It works better if you plug it in.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: adding/subtracting times
« Reply #5 on: July 27, 2020, 06:41:16 pm »
Here is R Frost work made more portable:
Code: QB64: [Select]
  1. _TITLE "Time difference" 'b+ mod r frost 2020-07-27
  2.  
  3. ' ref r frost 2020-07-27   https://www.qb64.org/forum/index.php?topic=2861.msg121256#msg121256
  4. ' math with hh:mm:ss.dd
  5.  
  6. DIM t1$, t2$, f1!, f2!
  7. 't1$ = "10:17:12.45"
  8. 't2$ = "11:53:52.18"
  9. t1$ = "12:00:00.25" ' from noon and 1/4 sec
  10. t2$ = TIME$ '
  11. f1! = timeStr2Secs!(t1$)
  12. f2! = timeStr2Secs!(t2$)
  13.  
  14. PRINT "+"; t2$, f2!
  15. PRINT "-"; t1$, f1!
  16. PRINT "============================"
  17. PRINT secs2TimeStr$(f2! - f1!), INT(f2! - f1! + .5)
  18.  
  19. FUNCTION timeStr2Secs! (timeStr$)
  20.     DIM hh AS INTEGER, mm AS INTEGER, s!
  21.     hh = VAL(MID$(timeStr$, 1, 2))
  22.     mm = VAL(MID$(timeStr$, 4, 2))
  23.     s! = VAL(MID$(timeStr$, 7, 5))
  24.     timeStr2Secs! = hh * 60 * 60 + mm * 60 + s!
  25.  
  26. FUNCTION secs2TimeStr$ (secs!)
  27.     DIM hh AS INTEGER, mm AS INTEGER, s!, h$, m$, s$
  28.     hh = secs! \ 3600
  29.     mm = (secs! - hh * 3600) \ 60
  30.     s! = (secs! - hh * 3600 - mm * 60)
  31.     s! = INT(s! * 100) / 100
  32.     h$ = RIGHT$("00" + LTRIM$(STR$(hh)), 2)
  33.     m$ = RIGHT$("00" + LTRIM$(STR$(mm)), 2)
  34.     s$ = xDP$(s!, 2)
  35.     secs2TimeStr$ = h$ + ":" + m$ + ":" + s$
  36.  
  37. FUNCTION xDP$ (x, DP)
  38.     DIM test$, p AS INTEGER
  39.     test$ = _TRIM$(STR$(INT(x * 10 ^ DP) / 10 ^ DP))
  40.     p = INSTR(test$, ".")
  41.     IF p = 0 AND DP <> 0 THEN test$ = test$ + "." + STRING$(DP, "0")
  42.     IF p AND DP = 0 THEN test$ = LEFT$(test$, LEN(test$) - 1)
  43.     xDP$ = test$
  44.  
  45.  

EDIT: 2nd function made more agreeable to OPTION _EXPLICIT
EDIT: fixed s$ in second function (I think).
« Last Edit: July 27, 2020, 07:17:48 pm by bplus »

Offline Dimster

  • Forum Resident
  • Posts: 500
    • View Profile
Re: adding/subtracting times
« Reply #6 on: July 28, 2020, 10:02:44 am »
Hi JohnUKresults - Just curious about the decimal places you are using - are they fixed values for the Day? and the decimal would range from 01 being day 1 and .31 is for the 31st day of the month.  Or would the decimal be the full range of a year using 365 days ( ie say we have  July 28 = 210/365 = .57)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: adding/subtracting times
« Reply #7 on: July 28, 2020, 10:48:11 am »
Hi JohnUKresults - Just curious about the decimal places you are using - are they fixed values for the Day? and the decimal would range from 01 being day 1 and .31 is for the 31st day of the month.  Or would the decimal be the full range of a year using 365 days ( ie say we have  July 28 = 210/365 = .57)

Hi @Dimster

You are missing:

Quote
(time of day stored to 2 decimal places)

It seems to be 2 decimal places on the seconds of the time of day. I think you can get that degree of accuracy off the TIMER function which gives seconds (and parts of them) elapsed since midnight.


Oh hey great test /demo of secsToTimeStr$() Function!
Code: QB64: [Select]
  1. WHILE _KEYDOWN(27) = 0
  2.     CLS
  3.     PRINT secs2TimeStr$(TIMER(.001))  '<<<<<<<<<< test demo of function!
  4.     PRINT TIME$
  5.     _DISPLAY
  6.     _LIMIT 60
  7.  
  8.  
  9. FUNCTION secs2TimeStr$ (secs!)
  10.     DIM hh AS INTEGER, mm AS INTEGER, s!, h$, m$, s$
  11.     hh = secs! \ 3600
  12.     mm = (secs! - hh * 3600) \ 60
  13.     s! = (secs! - hh * 3600 - mm * 60)
  14.     s! = INT(s! * 100) / 100
  15.     h$ = RIGHT$("00" + LTRIM$(STR$(hh)), 2)
  16.     m$ = RIGHT$("00" + LTRIM$(STR$(mm)), 2)
  17.     s$ = xDP$(s!, 2)
  18.     secs2TimeStr$ = h$ + ":" + m$ + ":" + s$
  19.  
  20. FUNCTION xDP$ (x, DP)
  21.     DIM test$, p AS INTEGER
  22.     test$ = _TRIM$(STR$(INT(x * 10 ^ DP) / 10 ^ DP))
  23.     p = INSTR(test$, ".")
  24.     IF p = 0 AND DP <> 0 THEN test$ = test$ + "." + STRING$(DP, "0")
  25.     IF p AND DP = 0 THEN test$ = LEFT$(test$, LEN(test$) - 1)
  26.     xDP$ = test$
  27.  
  28.  
  29.  
« Last Edit: July 28, 2020, 10:56:22 am by bplus »

Offline Dimster

  • Forum Resident
  • Posts: 500
    • View Profile
Re: adding/subtracting times
« Reply #8 on: July 28, 2020, 11:57:57 am »
Ohhhh - when I saw dd - I thought that was referring to the day.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: adding/subtracting times
« Reply #9 on: July 28, 2020, 12:28:05 pm »
I miss things too (often) like I am seeing now those 2 time conversion functions can be (need to be?) improved!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: adding/subtracting times
« Reply #10 on: July 28, 2020, 04:53:01 pm »
Man this hh:mm:ss.dd timeStr$ format was real b... trying to get the string to do decimals correctly! I discovered a trick.

Code: QB64: [Select]
  1. _TITLE "secs2TimerStr$ test and demo" ' b+ 2020-07-28
  2. ' 2020-07-28 fix leading 0 or 00 for secs, dump xDP$ function
  3.  
  4. PRINT secs2TimeStr$(60) '            00:01:00.00
  5. PRINT: PRINT secs2TimeStr$(61) '     00:01:01.00
  6. PRINT: PRINT secs2TimeStr$(0) '      00:00:00.00
  7. PRINT: PRINT secs2TimeStr$(75.15) '  00:01:15.15
  8. PRINT: PRINT secs2TimeStr$(60.025) ' 00:01:00.03  roundup
  9. PRINT: PRINT secs2TimeStr$(60.005) ' 00:01:00.01  roundup
  10. PRINT: PRINT secs2TimeStr$(60.004) ' 00:01:00.00  no roundup
  11.  
  12. FUNCTION secs2TimeStr$ (secs!) ' format hh:mm:ss.dd  ver 2020-07-28 fix leading 0 in seconds
  13.     DIM hh AS INTEGER, mm AS INTEGER, s!, h$, m$, s$
  14.     hh = secs! \ 3600
  15.     mm = (secs! - hh * 3600) \ 60
  16.     s! = (secs! - hh * 3600 - mm * 60)
  17.     h$ = RIGHT$("00" + LTRIM$(STR$(hh)), 2)
  18.     m$ = RIGHT$("00" + LTRIM$(STR$(mm)), 2)
  19.     s$ = _TRIM$(STR$(100 + s! + .005)) 'get rid of the E's
  20.     s$ = MID$(s$, 2, 5)
  21.     secs2TimeStr$ = h$ + ":" + m$ + ":" + s$
  22.  
  23.  
  24.  

Offline Bert22306

  • Forum Regular
  • Posts: 206
    • View Profile
Re: adding/subtracting times
« Reply #11 on: July 28, 2020, 11:51:43 pm »
I also thought, initially, that the dd referred to day. But instead, it meant "decimal." When I do this sort of thing, defining ASCII numbers and their precision, my approach is to use something more like hhmmss.ss.

Anyway, I also thought that TIMER provided seconds of the day to 2 decimal places. Instead, it appears to be 5 decimal places. Unless I'm looking at some sort of artifact.

Try this out. I didn't do any fancy formatting, using colons, but the results are simple enough. I deliberately did not round the INT functions, because in this type of use, usually, you don't to go past the whole hour, or the whole minute, or midnight, prematurely.

Code: [Select]
_TITLE "Test INT function for hours, minutes, seconds"
SCREEN _NEWIMAGE(120, 43, 0)
COLOR 1, 7
CLS
1 INPUT "Continue or exit (x to exit)"; cont$
IF cont$ = "x" THEN END
PRINT
TOD = TIMER
Hours = INT(TOD / 3600)
Minutes = INT((TOD - (Hours * 3600)) / 60)
Seconds = TOD - Hours * 3600 - Minutes * 60
PRINT "TOD seconds = "; TOD
PRINT "Hours = "; Hours; "  Minutes = "; Minutes; "  Seconds = "; Seconds
PRINT
GOTO 1
END

If you only want whole seconds, then change the Seconds line to:

Seconds = INT(TOD - Hours * 3600 - Minutes * 60)
« Last Edit: July 29, 2020, 05:10:17 am by Bert22306 »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: adding/subtracting times
« Reply #12 on: July 29, 2020, 12:19:52 pm »
Anyway, I also thought that TIMER provided seconds of the day to 2 decimal places. Instead, it appears to be 5 decimal places. Unless I'm looking at some sort of artifact.

Remember guys, TIMER has an optional parameter for precision...

https://www.qb64.org/wiki/TIMER

PRINT TIMER
PRINT TIMER (0.01)
PRINT TIMER (0.0001)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: adding/subtracting times
« Reply #13 on: July 29, 2020, 12:36:49 pm »
Remember guys, TIMER has an optional parameter for precision...

https://www.qb64.org/wiki/TIMER

PRINT TIMER
PRINT TIMER (0.01)
PRINT TIMER (0.0001)

Yes and here is a demo with the better conversion function:
Code: QB64: [Select]
  1. _TITLE "secs2TimeStr$ Demo 2" 'b+ 2020-07-29
  2.  
  3. WHILE _KEYDOWN(27) = 0
  4.     CLS
  5.     PRINT secs2TimeStr$(TIMER(.001)) '<<<<<<<<<< test demo of function!
  6.     PRINT TIME$
  7.     _DISPLAY
  8.     _LIMIT 11 'some odd franction of a second
  9.  
  10.  
  11. FUNCTION secs2TimeStr$ (secs!) ' format hh:mm:ss.dd  ver 2020-07-28 fix leading 0 in seconds
  12.     DIM hh AS INTEGER, mm AS INTEGER, s!, h$, m$, s$
  13.     hh = secs! \ 3600
  14.     mm = (secs! - hh * 3600) \ 60
  15.     s! = (secs! - hh * 3600 - mm * 60)
  16.     h$ = RIGHT$("00" + LTRIM$(STR$(hh)), 2)
  17.     m$ = RIGHT$("00" + LTRIM$(STR$(mm)), 2)
  18.     s$ = _TRIM$(STR$(100 + s! + .005)) 'get rid of the E's
  19.     s$ = MID$(s$, 2, 5)
  20.     secs2TimeStr$ = h$ + ":" + m$ + ":" + s$
  21.  
  22.  
  23.  
  24.  
  25.  

Offline JohnUKresults

  • Newbie
  • Posts: 40
    • View Profile
Re: adding/subtracting times
« Reply #14 on: August 05, 2020, 11:20:45 am »
Hi guys

Thanks for all your input. All very helpful.

To clarify, the time in the reader I am accessing is stored as a full time of day with the date and then the time, with seconds to 2 decimal places, stored in a string like this:
15/03/2020 10:53:04.77

I've managed now to strip out the times, and worked out a small subroutine which slices the time up into variables for hours, minutes and seconds, then converts that all to seconds, so I can subtract one decimal number of seconds from another, and then I can convert the result back to a string (rounded up to whole seconds in that final conversion).

I can't use TIMER as I'm not accessing times on my pc - just on an external reader.

Grateful for all your very useful responses and snippets of code.

John