Date/time calculations

In the Date/time values tutorial, we demonstrated a few basic ways to parse and analyze dates. This tutorial shows how to do two common calculations with dates:

  • Combine month and year values into a single date
  • Time interval calculations

Convert separate date values to strings

Surveys may elicit dates, not as dates, but as separate questions (e.g. year, month, day). We can use data process to convert these into date strings that Protobi can recognize. 

Consider a question that asked for month and year separately: 

Protobi data view displaying question q1 'Enter a date' split into two child elements: q1_1 showing month distribution (January 10.2%, February 12.8%, through December 1.8%) and q1_2 showing year distribution with 2019 dominating at 72.1% of 226 responses.

Note: The month values in q1_2 are actually numeric, and month names are the format.

Protobi 'Edit format' dialog box displaying a table with columns for Value, Format, Sort as, Sort last, Hide, and Remove. The Value column shows numbers 1-12, Format column shows corresponding month names (January through December), with a checked option to 'Group unformatted values into [other]' and a 'Clear all formats' link at the bottom.

Create the process

To convert month and year from the above example into date strings, create a data process:

  • Go to the data tab of your project 
  • Create a new process (or edit an existing process) 
  • Set the process as primary
  • Press "Edit/Run" to get to process code page
  • Paste in the code (from below)
  • Press run, and save.

Convert to date strings code

The code starts with a simple return rows, which just returns an array containing your dataset. The program iterates over this array and creates a new data column for row.q1 that concatenates the month and year values into strings.

We used an existing key "row.q1" as the element that will contain the string values. However, you can make up a new key which will write a new element containing the date strings into existence. 

Expand to see the code

For the date fields enter:

  • key: Parent group's key can be used or use a new key 
  • month: Month element's key
  • year: Year element's key
var rows = data.main;

// Convert Month/Year pairs to date stringsvar date_fields = [
  {key:  "q1",   month: "q1_1", year: "q1_2"}, // combine q1 month and year
  {key:  "q2",   month: "q2_1", year: "q2_2"}, // combine q2 month and year
  {key:  "q3",   month: "q3_1", year: "q3_2"}, // combine q3 month and year

]

rows.forEach(function(row){
    _.each(date_fields, function(entry) {
        if (row[entry.year]) {
            var date_str = row[entry.year] + '-' + row[entry.month].padStart(2, '0') + '-01' + 'T12:00:00'
            row[entry.key] = date_str//moment(date_str, 'YYYY-MM')
        }
    })

return rows

Open your project. If it's already open, refresh the page. Keys that didn't previously exist, but were written into existence in the code should be in fields. 

Once you find the element containing the date strings, in element properties change type from "empty" to "date" (seen here). 

Result

Below, we see q1 is populated with the resulting date strings. The dates are not in ISO date format, but you can customize date formats in JSON.

You can hide, remove, or delete the separate month and year child elements . 

Protobi interface displaying question q1 'Enter a date' with raw timestamp data (dates like '6/1/2009, 12:00:00 PM', '1/1/2010, 12:00:00 PM', etc. all showing 0.4% or 0.9%) in the top section, and below it two extracted components: q1_1 showing months 1-12 with their percentages, and q1_2 showing years 2009-2019 with 2019 at 72.1%.

Transform dates

For groups with type "date" you can transform to a unit of time (e.g. year, quarter, etc.): 

Protobi 'Transform group' dialog showing radio button options for calculating parent group values from children. The 'Year' option is selected among choices including None, Sum, Mean, Median, Min, Max, Std Dev, Condense, Compact, Year, Quarter, Month, Day, Hour, Day name, and Day of week, with a 'Hide children' checkbox at the bottom.

Below, we transformed q1 to year and hid children:

Protobi data view showing question q1 'Enter a date' with italic subtitle 'Transform to year', displaying extracted year values 2008-2018 with their percentages, where 2018 dominates at 72.1%, followed by 2017 at 17.3%, and earlier years showing minimal percentages (all under 4%), total N=226.

Calculate time between dates

We can also use process code to calculate time intervals. In the example below, we want to calculate the time between dates entered in q3 and q4. 

Protobi interface displaying two date questions side by side: q3 'Date for q3' showing dates from 5/1/2013 through 4/1/2019 (with 4/1/2019 at 5.3%), and q4 'Date for q4' showing dates from 6/1/2009 through 12/1/2017, both with Filter boxes and Apply buttons, displaying full timestamps in M/D/YYYY, HH:MM:SS AM/PM format with percentage distributions.

Time interval code

Set up the data process (see steps above) but paste in the time interval code seen below.

You can delete or add rows of code as necessary, depending on how many time intervals you need to calculate. 

For the time fields enter:

  • key: Create a key that can be easily found and identified (e.g. q3_q4)
  • start: Start time (e.g. q3)
  • end: End time (e.g. q4)
  • unit: Unit of measurement for the interval (e.g. month, year)

 Press run, and save. 

Time interval in months

var rows = data.main;
function getAbsoluteMonths(dt) {
  var momentDate = moment(new Date(dt))
  var months = Number(momentDate.format("MM"));
  var years = Number(momentDate.format("YYYY"));
  return months + (years * 12);
}

function getMonthsBetween(end, start) {
    if (end && start) return  getAbsoluteMonths(end) - getAbsoluteMonths(start)
    else return null
}
// Convert date strings to time intervals
var date_intervals = [
    {key: "q3_q4", start: "q3", end: "q4", unit: 'month'}, // q3 date to q4 date
    {key: "q4_q5", start: "q4", end: "q5", unit: 'month'}, // q4 date to q5 date

]

// convert dates to intervals
rows.forEach(function(row) {

    _.each(date_intervals, function(entry) {
        if (row[entry.start] && row[entry.end]) {
            var start = moment(row[entry.start], 'YYYY-MM')
            var end = moment(row[entry.end],'YYYY-MM')
            row[entry.key] =  getMonthsBetween(end, start)
        }
    })

})

return rows

Difference in weeks

var rows = data.main;

// Enter key (new variable name for the time intervals) and start/end variables
var date_intervals = [
    {key: "q3_q4", start: "q3", end: "q4", unit: 'weeks'}, // q3 date to q4 date
    {key: "q4_q5", start: "q4", end: "q5", unit: 'weeks'}, // q4 date to q5 date

]

//Define the function that specifies format for the difference between dates
function getAbsoluteWeeks(dt) {
    var momentDate = moment(new Date(dt))
    var weeks = momentDate.weeks()
    var dates = Number(momentDate.format("DD"));
    var months = Number(momentDate.format("MM"));
    var years = Number(momentDate.format("YYYY"));
    return weeks + (years * 52);
}

//Define the function that calculates the difference between dates
function getWeeks(end, start) {
    if (end && start) return  getAbsoluteWeeks(end) - getAbsoluteWeeks(start)
    else return null
}

// Convert date strings to time intervals
//Below the start/end date format is MM/DD/YYYY. The dates in your project may be in a different format, adjust accordingly.
rows.forEach(function(row) {
    
    _.each(date_intervals_weeks, function(entry) {
        if (row[entry.start] && row[entry.end]) {
            var start = moment(row[entry.start], 'MM/DD/YYYY')
            var end = moment(row[entry.end],'MM/DD/YYYY')
            row[entry.key] =  getWeeks(end, start)
        }
    })
    
})

return rows

Result

Open your project (or refresh the page). The interval elements should be in fields because they were written into existence in the code. You can use the tree to search for elements if you're having trouble locating them. 

Protobi data view displaying 'q3_q4' variable with calculated month differences between two dates. The distribution shows [NA] at 27.0%, value 0 at 29.6%, and negative value -1 at 14.6% as the top three categories, followed by various positive and negative integer values (113, 90, 34, 25, 18, 11, 10, 9, 6, 4, 3, 2, 1, -2, -3) each showing smaller percentages between 0.4% and 6.6%.

In this tutorial, we discussed two common types of date/time calculations that can be done in Protobi. Your Protobi project may need different or more complex time calculations not yet written here. Contact support@protobi.com and we'll help you get setup for your case.