This page contains:
In CommCare you can do calculations with dates and times just like you would with numbers or strings, and there are a few CommCare Functions that are useful for doing so. The key ones explained here are:
| |
| For Web Apps it returns the current server date, but in the browser's time zone. E.g.:
|
| For Web Apps it returns the current server date/time value, but in the browser's time zone. E.g.:
|
More details about these functions, and other functions that may be useful for performing calculations with dates, can be found here.
For further guidance on doing calculations with dates and times, see Hidden Values Tutorial Part 2: Calculations Using a Date.
Age in years (estimate):
int((today() - date(#form/dob)) div 365.25) |
Age in years (precise):
if(format-date(today(), "%m%d") >= format-date(#form/dob, "%m%d"), format-date(today(), "%Y") - format-date(#form/dob, "%Y"), format-date(today(), "%Y") - format-date(#form/dob, "%Y") - 1) |
Age in months:
int((today() - date(#form/dob)) div 30.4) |
Age in months (by day of month)
(format-date(today(), "%Y") - format-date(#form/dob, "%Y")) * 12 + (format-date(today(), "%m") - format-date(#form/dob, "%m")) + if(format-date(today(), "%d") < format-date(#form/dob, "%d"), -1, 0) |
Age in weeks:
int((today() - date(#form/dob)) div 7) |
Estimated Date of Delivery (EDD) from Last Menstrual Period (LMP):
date(#form/lmp + 280) |
This is an example of a hidden value where the Estimated Date of Delivery (EDD) is being calculated. The logic statement goes in the "Calculation Condition" box:
The following shows how to restrict a Date question's answer to be within a certain range:
One important concept to understand about dates in CommCare is that a date value can often stored in a string or numeric format, rather than as a Date type, but any date computations need to be performed on arguments that are actually of the type date. So when you have a date value that may be of type string or numeric rather than of type date, you can use date() to convert it before doing computations. Some examples:
In CommCare, you can use the now() function to get the current date and time.
To perform any computations using now(), make sure to consider the following:
Because the result of now() contains time data in addition to date data, you cannot do math or comparisons on this data type directly, and you also should not convert it to a date using date(), or the time portion will be dropped. Instead, you must first convert it to a numeric representation, using the function double(), and then do any desired computations.
Similarly, if you are saving the value of now() as a case property, you must convert it to a number before saving it as a case property, i.e. double(now()). This will convert the now() value to a number that represents the date/time in days since January 1, 1970. Saving now() directly will only save the date portion without the time portion.
As an example of doing computations using now(), suppose you want to compute the amount of time a user spends doing some activity/workflow. You could achieve this by doing the following:
In the form that represents the beginning of the workflow, you can capture the full date and time in a hidden value with the calculation:
double(now()) |
Then to compute the time elapsed, you would use:
double(now()) - double(#form/start_time) |
The result is a decimal value in days/fractions of days. To convert to the # of hours (rounded down), you could use the following calculation:
int(#form/time_worked * 24) |
To convert now() to a date and time in excel:
To extract a nicely-formatted time from now():
Create a hidden value called double_now to store the value of now():
double(now()) |
Create a hidden value called seconds_since_midnight to store only the time, represented as the number of seconds since midnight:
(#form/double_now - floor(#form/double_now)) * 24 * 60 * 60 |
You can then create an hours hidden value:
floor(#form/seconds_since_midnight div 60 div 60) |
And a minutes hidden value:
floor((#form/seconds_since_midnight - (#form/hours * 60 * 60)) div 60) |
And a seconds hidden value:
floor(#form/seconds_since_midnight mod 60) |
And finally display the time nicely:
concat(#form/hours, ':', #form/minutes, ':', #form/seconds) |
Note that this will display the time in 24-hour format and will not zero-pad, so 2:05:30 in the afternoon would display as 14:5:30. You can use if statements in the formatted time calculation to address this.
To convert or format a date into another format (e.g. day of week, name of month, etc.) see the format-date function.
When you enter day, month, and year in as three separate numerical responses, you can convert those three responses into one date as follows
You can use time collected in forms to do different calculations, e.g. the number of hours between the time of birth and now. Some things to keep in mind when doing these calculations:
Calculate minutes since midnight for the time of birth (call this #form/minutes_since_midnight_birth):
substr(#form/time_of_birth, 0, 2) * 60 + substr(#form/time_of_birth, 3, 5) |
Convert minutes since midnight into a decimal, by dividing it by the total number of minutes in a day (call this #form/time_of_birth_decimal):
#form/minutes_since_midnight div 1440 |
Sum that numeric time with a numeric version of the dob. This will get you to a numeric datetime value like 16925.50833333 (call this #form/birth_datetime):
double(#form/dob) + #form/time_of_birth_decimal |
Then, in the form where you need the hours calculation, subtract your datetime from double(now()) and convert to hours (call this #form/hours):
(double(now()) - #form/birth_datetime) * 24 |
If you wish, you can also use the round() function to output a rounded # of hours:
round(#form/hours) |