© 2024 IQVIA - All Rights Reserved
Incomplete/Partial DateTime Future Check
Summary
This edit check compares the specified timing components of an Incomplete or Partial DateTime Item against the current date/time to ensure that the specified timing components are not in the future. This edit check is useful because the ‘Disallow Future Date’ Item setting only works for full DateTime Item datatypes.
Formal Expression
function getTimeZoneOffset(timeZoneId) {
var timezoneOffsets = {
"US/Pacific": -7 * 60 * 60 * 1000,
"US/Mountain": -6 * 60 * 60 * 1000,
"US/Central": -5 * 60 * 60 * 1000,
"US/Eastern": -4 * 60 * 60 * 1000,
"Europe/London": 0 * 60 * 60 * 1000,
"Europe/Berlin": 1 * 60 * 60 * 1000,
"Europe/Paris": 1 * 60 * 60 * 1000,
"Europe/Madrid": 1 * 60 * 60 * 1000,
"Europe/Rome": 1 * 60 * 60 * 1000,
"Europe/Warsaw": 1 * 60 * 60 * 1000,
"Europe/Moscow": 3 * 60 * 60 * 1000,
"UTC": 0 * 60 * 60 * 1000,
"GMT": 0 * 60 * 60 * 1000,
};
return timezoneOffsets[timeZoneId] || 0;
}
function normalizeIncompleteDatetime(value, timeZoneId) {
logger("Original value: " + value);
// Split the date and time parts
var parts = value.split('T');
var datePart = parts[0].split('-');
// Default year, month, and day
var year = datePart[0] ? parseInt(datePart[0], 10) : 0;
var month = datePart[1] && datePart[1].trim() !== '' ? parseInt(datePart[1], 10) - 1 : 0; // Default to January (month = 0)
var day = datePart[2] && datePart[2].trim() !== '' ? parseInt(datePart[2], 10) : 1; // Default to 1st of the month
// Split the time part and pad missing parts with defaults
var timePart = parts.length > 1 ? parts[1].split(':') : [];
var hour = timePart[0] && timePart[0].trim() !== '' ? parseInt(timePart[0], 10) : 0;
var minute = timePart[1] && timePart[1].trim() !== '' ? parseInt(timePart[1], 10) : 0;
var second = timePart.length > 2 && timePart[2].trim() !== '' ? parseInt(timePart[2], 10) : 0;
// Create the Date object directly in the local timezone
var normalizedDatetime = new Date(year, month, day, hour, minute, second);
// Check if the date is valid
if (isNaN(normalizedDatetime.getTime())) {
logger("Error: Invalid Date created from input value.");
customErrorMessage('The datetime "' + value + '" could not be interpreted as a valid date.');
return null;
}
// Adjust the datetime according to the timezone offset
var timezoneOffset = getTimeZoneOffset(timeZoneId);
normalizedDatetime = new Date(normalizedDatetime.getTime() - timezoneOffset); // Corrected: Subtracting the offset to convert from MT to UTC
logger("Date object adjusted for " + timeZoneId + ": " + normalizedDatetime);
return normalizedDatetime;
}
function isNotInFuture(datetimeValue, timeZoneId) {
logger("Starting isNotInFuture check...");
// Normalize the incomplete datetime value directly in the timezone
var normalizedDatetime = normalizeIncompleteDatetime(datetimeValue, timeZoneId);
if (!normalizedDatetime) {
// Return false if we couldn't create a valid date
return false;
}
logger("Normalized datetime for comparison: " + normalizedDatetime);
// Get the current time adjusted to the local timezone
var now = new Date();
logger("Current local time: " + now);
// Compare the datetime
if (normalizedDatetime.getTime() >= now.getTime()) {
var errorMessage = 'The datetime "' + datetimeValue + '" is in the future or exactly at the current time, which is not allowed.';
logger("Error: " + errorMessage);
customErrorMessage(errorMessage);
return false;
}
logger("Datetime is not in the future.");
return true;
}
// Extract the timezone from formJson
var timeZoneId = formJson.form.subject.volunteer.site.timeZoneId;
logger("TimeZone ID: " + timeZoneId);
// Run the check against the provided item value
logger("Item value: " + itemJson.item.value);
var isValid = isNotInFuture(itemJson.item.value, timeZoneId);
logger("Validation result: " + isValid);
return isValid;
Edit Check Walkthrough
Exported and Printed Copies Are Uncontrolled