Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Add hours and minutes to give a total 3

Status
Not open for further replies.

Steve-vfp9user

Programmer
Feb 5, 2013
337
GB
Guys

I have a form with seven days made up of each day (e.g. Monday, Tuesday etc) and a total field. The field are numeric 5,2 but originally were numeric 5

The reason for the change is that some of the hours submitted are 4.30 (being 4 hours 30 minutes) or 3.45 (3 hours 45 minutes) to name a few.

Previously it was easy to add to whole number e.g. 4, 6, 7 etc but I'm struggling with how to add up hours and minutes to give a total hours and minutes.

Some of the threads I found talk about converting seconds to minutes or using a timedate field but as we are already using this program I was wondering how I go about adding up the fields shown above.

Previously in the lost focus procedure of each "day" field we have:

Replace total with Monday+Tuesday+Wednesday etc

What's the best way to achieve this please?

Thank you

Steve
 
Replace total with NumToTime(Monday) + NumToTime(Tuesday) + etc.. etc..


FUNCTION NumToTime()
PARAMETERS tnAmount
lnHours = INT(tnAmount)
lnMin = SUBSTR(TRANSFORM(tnAmount),AT('.',TRANSFORM(tnAmount))+1)
lnMin = VAL(lnMin)
lnMin = lnMin/60
return lnHours + lnMin
ENDFUNC


Ez Logic
Michigan
 
One possibility.

Code:
Monday=7
Tuesday=4.30
Wednesday=3.45


lnH1 = INT(Monday) + INT(Tuesday) + INT(Wednesday)
lnM1 = Monday + Tuesday + Wednesday - lnH1
lnM = lnM1 % 0.6
lnH = lnH1 + INT((lnM1 - lnM)*5/3)

? lnH + lnM

Or a single formula :

Code:
Replace total with ;
 INT(Monday) + INT(Tuesday) + INT(Wednesday) + INT(((Monday + Tuesday + Wednesday - ;
 (INT(Monday) + INT(Tuesday) + INT(Wednesday))) -(Monday + Tuesday + Wednesday - (INT(Monday) + INT(Tuesday) + INT(Wednesday))) % 0.6)*5/3) + 
 (Monday + Tuesday + Wednesday - (INT(Monday) + INT(Tuesday) + INT(Wednesday))) % 0.6


Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
I would change the way you enter times. 1:30 is 1.5 hours and not 1.30 and to enter the times this way is simply leading to such unnecessary trouble.

How about a textbox with inputmask 99:99?
Or how about setting the textbox to a datetime value? Simply set the value property to {//:} and you have an empty datetime.

You later can simply calculate with the datetimes.

Bye, Olaf.
 
I completely agree with Olaf. You are entering the wrong value for minutes which is most likely the main reason why you are having trouble summing up the total time.

kilroy [knight]
philippines

"Once a king, always a king. But being a knight is more than enough."
 
I disagree with Olaf and Kilroy. Entering, say, 3.45 is more natural for users than entering 3.75. And besides, the users are already used to doing that, so changing it could cause confusion.

You shouldn't force the users to use a more difficult method just to save the programmer a few lines of code.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Well Mike,

I don't suggest letting the user enter 3.75 instead of 3.45, I am suggesting using string format in normal time format with : or even a datetime value, then you don't have such compuation needs.

If you let users enter datetimes, you already are in datetime format and can subtract midnight from the same date to get just the time portion.

Times entered as string 3:45 obviously have to be converted somehow, but you can do that with CTOT or EVAL of datetime literals, which you put together with the user input, eg ? (EVAL('{^1900-01-01 '+textbox.value+':00}')- Datetime(1900,1,1)) 3600 will result in 3.75 for a user input (textbox.value) of "3:45".

This kind of one line code is easier to understand and maintain than the decimal calculations suggested, isn't it?

Bye, Olaf.
 
I dunno Mike. But around here in the office, people fairly recognize that 1.45 hours is not 1 hour and 45 minutes but 1 hour and 27 minutes instead. Again, like Olaf said, maybe the way the user enters the time value should be changed to a more common, or shall I say, "standard" time notation.

Just my two cents. [thumbsup2]

kilroy [knight]
philippines

"Once a king, always a king. But being a knight is more than enough."
 
Olaf, you said: "1:30 is 1.5 hours and not 1.30". That suggested to me that you were saying that the users should enter 1.5 for half past one. Are you in fact saying they should enter 1:30 with a colon, rather than 1.30 with a full stop?

That's surely a regional issue, as different countries use different separator characters (just as with decimal points and thousand separators). Plus, it depends on what the users are used to in this particular case.

If that is what you are saying, then how about going one step further, and having two text boxes: one clearly labelled "hours" and the other "minutes". That would be competely clear and unambiguous. Of course, Steve would still have to convert the minutes to fractions of an hour, but that would be fairly trivial.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
>it depends on what the users are used to in this particular case

Anyway you shouldn't misuse decimals for times, even if a regional standard would be using . instead of : you can make it a text type textbox instead of a numeric textbox with an inputmask of 99.99.

When I said 1:30 is 1.5 hours I merely was talking about the math of it, you can't simply add 1.30 and 1.30 and expect the sum to be 3, as math of simple numbers applies here, while times are meant. I don't even know a region or locale having a full stop as separator between hours and minutes, but if that's the case you can surely apply the Inputmask and have a string input anyway.

The suggestions about the GUI follow right after, my two "How about" sentences.

For your satisfaction, how about rephrasing my first sentences this way:

I would change the way you enter times because to enter the times this way is simply leading to such unnecessary mathematical trouble. 1:30 is 1.5 hours and not 1.30 and so users should enter 1:30 instead of 1.3 and the calculations shouldn't modify numerical values in a complicated way with special handling of the fraction part, but users should enter times in a standard way and datetime conversion functions should do the math for you.

Bye, Olaf.
 
vgulielmus: Thank you for your post which I have implemented by adding your suggested code to each Lost Focus procedure in the fields for MONDAY, TUESDAY, WEDNESDAY etc

Ezlogic: Thank you for your post

Olaf and Torturedmind: I appreciate your suggestions however as ome of our users are let's say, an older element, asking them to convert 1 hour 45 minutes to 1.75 or 1 hour 40 minutes to 1.66 is well, not that good! The good old 1.30, 1.45, 1.20 etc is an easier option with regards to input

Mikelewis: I gave you a star because you more or less summed up what I've just said to Olaf and Torturedmind. I respect the comments made by others but as you have outlined,

"the users are already used to doing that, so changing it could cause confusion. You shouldn't force the users to use a more difficult method just to save the programmer a few lines of code"

I appreciate all your posts and comments on this thread, issue has been resolved.

Thank you

Steve
 
>asking them to convert 1 hour 45 minutes to 1.75
Again, this has never been suggested. Your code will do this, but not converting numeric to numeric, but string to datetime.

All you change is the textbox inputmask, no matter if it's 99:99 or 99.99, the entered values should not be treated as numeric, but as text, which is converted to datetime values.

The disadvantage of correcting numeric values is you have to do lot's more code, and what neither vgulielmus nor ezlogic have done is to handle cases of wrong input like 3.70. If you would add such checks, it's quite hard to do. If you convert strings like "3:30" or "3.30" or "3.70" into datetime values (you can convert 3.30 by first converting each . by a : for example) you get correct datetime values for correctly entered values and you get errors you can handle when converting a wrong entry like 3:70 or 3.70 into datetimes. You can then give a user friendly message informing them to make correct inputs.

Let's just take a look at the code of vgulielmus and feed in wrong input

Code:
Monday=7
Tuesday=4.90
Wednesday=3.45


lnH1 = INT(Monday) + INT(Tuesday) + INT(Wednesday)
lnM1 = Monday + Tuesday + Wednesday - lnH1
lnM = lnM1 % 0.6
lnH = lnH1 + INT((lnM1 - lnM)*5/3)

? lnH + lnM

This will output 16.15, because the .90 is counted as 90 minutes. The input error goes through undetected.

Even if you swear your users won't ever input such nonsense, you always have to take into account human error, even simply typos, for which a user can't be made responsible really. They are not intentionally, but should be addressed, if possible. Using the correct data type you only can enter correct value ranges, that's the big plus about this way.

Bye, Olaf.
 
The formula for error detection is :
llErr = Tuesday - INT(Tuesday) >= 0.6

Probably this is more complete :
llErr = (Tuesday - INT(Tuesday) >= 0.6) or !BETWEEN(Tuesday,0,24)

It's easy to create datetime variables from this numeric representation.

Code:
?ntot(7)
?ntot(4.30)
?ntot(23.59)
?ntot(0)
?ntot(0.59)
* Empty results, means erroneous values
?ntot(4.70)
?ntot(24.59)
?ntot(24)


FUNCTION ntot
	LPARAMETERS tnTime
	LOCAL lnH,lnM,ltTime
	lnH = INT(m.tnTime)
	lnM = (m.tnTime - m.lnH) * 100
	TRY
		ltTime = DATETIME(2000,1,1,m.lnH,m.lnM)
	CATCH
		ltTime = {// ::}
	ENDTRY
	RETURN ltTime
ENDFUNC

But even so, the summation requires an equivalent or alternate algorithm.


Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
from Mike said:
Olaf, you said: "1:30 is 1.5 hours and not 1.30". That suggested to me that you were saying that the users should enter 1.5 for half past one. Are you in fact saying they should enter 1:30 with a colon, rather than 1.30 with a full stop?

It is not a full stop after '1' but a decimal point, that is why ':' or any other charter but not the decimal. Also the user is not entering full spectrum of decimal digits for minutes, it stops at 59. So decimal is very much misleading and suggests that one could enter upto 99. Not everyone uses '.' for decimal point as you have suggested. VFP9User did not say anything about the '.' for his country. The user was entering integer data (hours only) and now they will be entering the minutes as well. For sure, it will be the decision of VFP9User or his users.

Nasib
 
It is not a full stop after '1' but a decimal point

No. The whole point is that it is not a decimal point. I deliberately didn't use the term "decimal point" because that would only apply in countries where that symbol is used to separate the integer from the fractional portion of a number. In many countries, a comma would be used instead, and perhaps other symbols elsewhere.

I used the term "full stop" because that describes the symbol, not the use to which the symbol might be put.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top