Automatic time calculation

Hi Everyone,

I am working on an electronic logbook for my first year students. in the
logbook there is a clock-in / clock-out module which contains forms to
clock in for the day and clock out at the end of the day. I would like to
calculate the hours and mins that they have worked and display it on the
clock out form when they are clocking out. I have seen commcare
documentation to support calculations using dates, but I am unsure of how
to calculate hours and minutes using time. is there a calculation/logic
for that?

Any help would be greatly appreciated!

Thanks,
Ameera

Ameera,

You can use the "now()" function to get the current date and time. To use
the result it in calculations, you must convert it to a decimal value using
the "double()" function. The double function will convert the now() value
to a number that represents the date/time in days. This is similar to doing
calculations on dates, when you use int() to convert a date value into
number of days.

When the user "checks in" in you can capture the full date and time with a
hidden value with a calculation:

double(now())

Save the hidden value to the case. When the user "checks out" you can load
that value into the "checks out" form (I'll call the hidden value
'log_in_time').

Create another hidden value (I'll call it 'time_worked') represent the
amount of time that has passed, by calculating:

double(now()) - double(/data/log_in_time)

The result is a decimal value in days/fractions of days. To convert to
hours and minutes, you can do the following calculations:

int(/data/time_worked * 24) = (rounded down) the # of hours

int(((/data/time_worked*24) - int(/data/time_worked * 24)) * 60) = (rounded
down) the # of minutes worked.

I know that's a little bit complex. Please let me know if you need a hand
testing anything out or getting this to work.

-Clayton

··· On Sun, Apr 13, 2014 at 10:33 AM, Ameera Hamid wrote:

Hi Everyone,

I am working on an electronic logbook for my first year students. in the
logbook there is a clock-in / clock-out module which contains forms to
clock in for the day and clock out at the end of the day. I would like to
calculate the hours and mins that they have worked and display it on the
clock out form when they are clocking out. I have seen commcare
documentation to support calculations using dates, but I am unsure of how
to calculate hours and minutes using time. is there a calculation/logic
for that?

Any help would be greatly appreciated!

Thanks,
Ameera

--
You received this message because you are subscribed to the Google Groups
"commcare-users" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to commcare-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Thanks Clayton,

I'm going to test it out and will let you know if i need more assistance.

Kind regards,
Ameera

··· On Sunday, 13 April 2014 16:33:23 UTC+2, Ameera Hamid wrote: > > Hi Everyone, > > I am working on an electronic logbook for my first year students. in the > logbook there is a clock-in / clock-out module which contains forms to > clock in for the day and clock out at the end of the day. I would like to > calculate the hours and mins that they have worked and display it on the > clock out form when they are clocking out. I have seen commcare > documentation to support calculations using dates, but I am unsure of how > to calculate hours and minutes using time. is there a calculation/logic > for that? > > Any help would be greatly appreciated! > > Thanks, > Ameera >

Hi Clayton,

I am working on this exact calculation in Commcare but its not working. What i want to capture is the time taken for a coaching session, see steps i took below:

We have two time questions, one for start_time and the other for end_time

hidden value(debut) = double(start_time)
hidden value(fin) = double(end_time)

hidden value(coaching_time) = hidden value(fin) - hidden value(debut)

//should i be converting before subtracting?

hidden value(convert_time) = int(((coaching_time * 24) *60))

Label : The total coaching time is : hidden value(convert_time)

I keep getting zero as an answer. please advise.

Hi,

Have you tried seeing what the intermediate value of each of those calculations is?

The Data Preview "Evaluate XPath" tool is very helpful for trying different calculations and seeing what the results are piece by piece to break down where issues are occuring.

Specifically:

We have two time questions, one for start_time and the other for end_time

hidden value(debut) = double(start_time)
hidden value(fin) = double(end_time)

I'm not sure that this is producing the result you might be hoping for, as I'm not sure that Time entry questions actual convert helpfully to numbers automatically.

-Clayton

Hi @Clayton_Sims,

My web apps view doesn't show me all the applications within my project space for me to test my expressions. Is there something i can do to rectify this?

Hi Jumai,

You should be able to see the Data Preview pane in Live Preview as well as in Web Apps.

Do you see the blue bar at the bottom of the Live Preview pane?

-Clayton

Hi Clayton,

Can you please send images to help me identify these features? Is the image below what you are referring to ?

image

Hi,

Within Live Preview you'd see the Data Preview Pane as a floating button on the lower right hand portion of the UI as in the screenshot below, underneath the "Submit" button

image.png

-Clayton

Okay, Seen.

Unfortunately the expressions aren't working. Does that mean the only option would be to do this after extracting the data from Commcare?

image

The other option would be to manipulate the times using the substring-before() and substring-after() functions to make your own integer representations of the times that are entered

IE:

int(substring-before(#form/timestart, ":")) * 60 + int(substring-after(#form/timestart, ":"))

would in theory produce a number of minutes that could be subtracted from a similar calculation for a "time of end", but that wouldn't properly calculate for times that 'wrap around' (IE: 11:30pm -> 1:30am) or other edge cases.

-Clayton

Unfortunately that still doesn't work for me, it doesn't seem to be parsing anything.

image

int(substring-before(#form/start_time, ':')) * 60 + int(substring-after(#form/start_time, ':'))

int(substring-before(#form/end_time, ':')) * 60 + int(substring-after(#form/end_time, ':'))

It's surprising to me that those expressions would ever be blank, I'd expect them to produce errors, "NaN", or '0' as an output if something wasn't right.

It would help to split up those expressions to try to pinpoint what parts of them are not producing the expected result.

Hi Jay,

Have you tried out the "Evaluate XPath" feature of Data Preview? In your screenshots, there is a "Menu" option in the top right. If you click that, you should see an option called "Evaluate XPath", which will take you to a screen where you can try out various expressions on the form without needing to reload everything each time. This should make it pretty quick to test out each part of those expressions to see where it's going wrong.

Note that instead of #form/timestart, you'll need to reference /data/timestart, as that #form syntax only works in the form builder.

Hi @Ethan_Soergel, @Clayton_Sims,

Been trying out the expressions using the Evaluate XPath feature but it still doesn't seem to understand the expression.

image

Ah, that's the problem - it should be /data/start_time, not #data/start_time. The expression tester doesn't support easy references. Additionally, the substring-before function takes two arguments. You can read more about it here. I believe the expression should be

int(substring-before(/data/timestart, “:”))

@Ethan_Soergel, @Clayton_Sims,

This is working now, i broke down the syntax in parts to evaluate.

(int(substring-before(/data/timestart, ":")) - int(substring-before(/data/timeend, ":")) ) * 60

@Ethan_Soergel, @Clayton_Sims

Hi guys,

Please how can i expand this function to take into account a duration less than 60mins?

int(substring-before(/data/timestart, “:”))
Gives the "hour" portion of the timestamp. To access the "minute" portion, use
int(substring-after(/data/timestart, “:”))

Clayton's message from earlier proposed this calculation:
int(substring-before(#form/timestart, “:”)) * 60 + int(substring-after(#form/timestart, “:”))

So in full, you could make a hidden value start_minutes with the calculation
int(substring-before(/data/timestart, “:”)) * 60 + int(substring-after(/data/timestart, “:”))
And a hidden value end_minutes with the calculation
int(substring-before(/data/timeend, “:”)) * 60 + int(substring-after(/data/timeend, “:”))

Then the overall result would be
/data/end_minutes - /data/start_minutes

I want to set up a system to check how long it takes for people to fill in sections of a single form (rather than use multiple forms). So I've used the double(now()) work-around.

However, hidden values are either instantiated immediately (using the default option), or every time a question is answered (using the calculate option). Even if I use the display condition, the hidden values will be instantiated every time a question is answered as soon as the display condition is met.

Is there no way to get hidden values to instantiate just once (say the first time the display condition is met) and then never again after? It might be a little bit error-prone to use if people decide to go back to previously answered questions, but given the vast majority of people just fill the form in a linear fashion from start to end, it should work fine most of the time.