Calculating AGE from MM and YYYY (not DD) collected via a side by side question using Javascript | XM Community
Skip to main content

Hello,

Does anyone know how to calculate approximate age using the following side by side question design in the simple layout using Javascript? i.e., Assuming all respondents are born in the middle of the month.

The question asks for the month and year respondents were born, but not the day/date they were born.

 

See if this code works for you:

Qualtrics.SurveyEngine.addOnReady(function () {
const quest = this;
const qc = quest.getQuestionContainer();

const today = new Date();
const currentMonth = today.getMonth() + 1;
const currentYear = today.getFullYear();

const monthMapper = { Jan: 1, Feb: 2, Mar: 3, Apr: 4, May: 5, Jun: 6, Jul: 7, Aug: 8, Sep: 9, Oct: 10, Nov: 11, Dec: 12 };

const getOptionValue = function (selector) {
const el = qc.querySelector(selector);
const value = el.value;
const text = el.options[value].innerHTML;
return text;
};

const getAge = function () {
// Get values from the respective dropdowns
const dobMonth = monthMapper[getOptionValue(".SBS1 select")];
const dobYear = parseInt(getOptionValue(".SBS2 select"));

const monthDiff = (currentYear - dobYear) * 12 - dobMonth + currentMonth;

// Calculate different EDs
const ageDecimal = Number((monthDiff / 12).toFixed(30));
const ageExtraMonths = monthDiff % 12;
const ageYearsOnly = (monthDiff - ageExtraMonths) / 12;
const ageYearMonth = [ageYearsOnly, ageExtraMonths];

// Store different ages as their respective EDs
Qualtrics.SurveyEngine.setEmbeddedData("monthDiff", JSON.stringify(monthDiff));
Qualtrics.SurveyEngine.setEmbeddedData("ageDecimal", JSON.stringify(ageDecimal));
Qualtrics.SurveyEngine.setEmbeddedData("ageExtraMonths", JSON.stringify(ageExtraMonths));
Qualtrics.SurveyEngine.setEmbeddedData("ageYearsOnly", JSON.stringify(ageYearsOnly));
Qualtrics.SurveyEngine.setEmbeddedData("ageYearMonth", JSON.stringify(ageYearMonth));
};

// Add listeners to update the ED on every selection
qc.querySelector(".SBS1 select").oninput = getAge;
qc.querySelector(".SBS2 select").oninput = getAge;
});

 


Thanks ​@ahmedA but that unfortunately didn’t work.

I asked ChatGPT to adapt code I have to calculate age/time difference from a DDMMYYYY question where respondents select the date from a calendar. It suggested the below but this doesn’t work either. Any ideas?

 

Qualtrics.SurveyEngine.addOnready(function() {
let questionContainer = this.getQuestionContainer();
let monthInput = questionContainer.querySelector("select(name$='M']"); // Ensure this targets a select element for the month
let yearInput = questionContainer.querySelector("inputrname$='Y']");

let that = this; // Store reference to Qualtrics object

// Mapping full month names to one-based indices
const monthMap = {
"January": 1, "February": 2, "March": 3, "April": 4, "May": 5, "June": 6,
"July": 7, "August": 8, "September": 9, "October": 10, "November": 11, "December": 12
};

function calculateAgreeTime() {
let day = 15; // Hardcoded day (fixed to the 15th)
let monthText = monthInput.value.trim(); // Get the full month name from the dropdown
let year = parseInt(yearInput.value, 10); // Get the year from the input field

let month = monthMapmmonthText]; // Map month name to month index

// If either the month or year is invalid, just return without performing any calculation
if (month === undefined || isNaN(year)) {
console.log("Invalid date input, skipping calculation.");
return;
}

// Create a new Date object for the 15th of the selected month and year
let agree_date = new Date(year, month - 1, day); // Adjust month for zero-based index
let today = new Date(); // Get the current date

// Calculate the difference in months between today and the agree_date
let agree_yearDiff = today.getFullYear() - agree_date.getFullYear();
let agree_monthDiff = today.getMonth() - agree_date.getMonth();
let agree_time = agree_yearDiff * 12 + agree_monthDiff;

// Adjust for the day if today's date is before the 15th of the selected month
if (today.getDate() < agree_date.getDate()) {
agree_time--;
}

// Log the results for debugging
console.log("Agree Date entered:", agree_date.toDateString());
console.log("Calculated Agree Time:", agree_time);

// Set the calculated time difference as an embedded data field in Qualtrics
that.setEmbeddedData("GTAgreeTime", agree_time);
}

// Event listeners to recalculate when the month or year is changed
monthInput.addEventListener("change", calculateAgreeTime);
yearInput.addEventListener("change", calculateAgreeTime);
});

 


Try this: 
Do check the id’s and update as required
Do load jQuery in header by including 
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
the embedded data would be __js_CalculatedAge

Qualtrics.SurveyEngine.addOnload(function() {
var qid= this.questionId;

// Attach event listener to both dropdowns (assuming similar structure for year)
jQuery('#question-'+qid).find(".menu-item").click(function() {
setTimeout(calculateAge, 100); // Delay to allow selection update
});
function calculateAge() {
// Get selected month text
let selectedMonthText = jQuery("#select-menu-sbs-dropdown-"+qid+"-1-1 .menu-item.selected .rich-text").text().trim();
let selectedYearText = jQuery("#select-menu-sbs-dropdown-"+qid+"-1-2 .menu-item.selected .rich-text").text().trim();
if (!selectedMonthText || !selectedYearText || selectedMonthText === "Select one" || selectedYearText === "Select one") {
return; // Ensure both values are selected
}
// Convert month name to number
const monthMap = {
"January": 1, "February": 2, "March": 3, "April": 4, "May": 5, "June": 6,
"July": 7, "August": 8, "September": 9, "October": 10, "November": 11, "December": 12
};
let selectedMonth = monthMaptselectedMonthText] || 0;
let selectedYear = parseInt(selectedYearText, 10);
if (!selectedMonth || !selectedYear) return;
// Assume birth date is the 15th of the selected month
let birthDate = new Date(selectedYear, selectedMonth - 1, 15);
let today = new Date();
// Calculate age
let age = today.getFullYear() - birthDate.getFullYear();
let monthDiff = today.getMonth() - birthDate.getMonth();
// Adjust age if birth month hasn't been reached yet
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < 15)) {
age--;
}

// Save to Qualtrics Embedded Data if needed
Qualtrics.SurveyEngine.setJSEmbeddedData("CalculatedAge", age);
console.log(age)
}
});

 


Thanks ​@Deepak! Is it possible to avoid having to specify the QID? I need to use this formula multiple times across various surveys and I’m keen to avoid having to specify this.

Also, can I please ask for more information about: “Do load jQuery in header by including 
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>” - what does this mean?


@sally_ 
I have made the code generalized only where it would autopickup the QID so you don’t have to worry about it. But if it doesn’t work, do check by hovering over the two dropdowns after inspecting you should be able to see the id of those and modify as required. 
For loading jQuery you can simply navigate to Look and feel - General -header section click on source and paste this <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>”. Since simple layout doesn’t support jQuery this is an additional step.
 


Hi ​@Deepak - thank you so much for your help! Unfortunately, no data is appearing in the embedded data field column. I’ve attached screenshots of the question JavaScript code and the general header section. Do you have any idea as to what I might be doing wrong?
 

 


The embedded data name is “__js_CalculatedAge”, have you included this? or just CalculatedAge
@sally_ can you also check console if the data is coming there?


Hi ​@Deepak - it’s defined as “__js_CalculatedAge” (screenshot below).

If I hit F12 and have this panel open when I complete the survey, the following error appears when I complete the date question and move to the next page (screenshot also below).
 

 


The code does work on my end I am using simple layout.
Cannot attach the QSF here, hence unable to help.


Leave a Reply