Working with dates and times
Medallia Experience Cloud treats date and time as a special kind of data. Expressions that reference dates or time can perform operations specific to this kind of data, such as extracting the month from a date, getting the difference in hours between two dates, or expressing a date in a different formatting pattern, etc.
Date types
Experience Cloud accepts different types of time and date objects. Primarily, it stores and handles dates as Joda Time type, but other types can also be used:
The format a date is stored in can be verified by looking at the importer script used to import the data, or alternatively, the script that populates the field. The table below shows the types that result from common ways to create dates:
| Type | Script to create |
|---|---|
org.joda.time.DateTime object | mydate = date(e_responsedate); |
| JavaScript Date object | mydate = new Date(); |
java.util.Date object | mydate = e_responsedate; |
| JavaScript string (not recommended) | mydate = Date(); |
If the script that originated the variable is not available, use the functions below to figure out its type. Use the k-field editor.
-
Use the
typeoffunction to tell if the variable is a string.
The result of this could either bereturn typeof mydate;stringorobject, but doesn't distinguish between different types of objects. -
If the variable is an object, use
getclass().getName()to tell the type of object.mydate.getClass().getName();
Use the following operations to transform date objects from one type to another:
-
To transform a JavaScript Date object into an
org.joda.time.DateTimeobject, wrap it in adate()operation:date(new Date()); -
To transform a
Java.util.Dateobject into anorg.joda.time.DateTimeobject, wrap it in adate()operation:date(e_responsedate); To transform an
org.joda.time.DateTimeobject into aJava.util.Dateobject, use thetoDate()operation:mydate.toDate();For example, see the code below used to shift the timezone for an
org.joda.time.DateTimeobject from PDT to CET, and, then convert this object to aJava.util.Dateobject, sinceformatDate()only works withJava.util.Dateobjects:var claimJodaDateCET = date(e_zurich_ch_claim_creation_datetime).withZone(org.joda.time.DateTimeZone.forID('Europe/Berlin')).withZoneRetainFields(org.joda.time.DateTimeZone.forID('US/Pacific')); var claimJavaDateCET = claimJodaDateCET.toDate(); var formattedClaimJavaDateCET = formatDate(claimJavaDateCET, 'dd.MM.yyyy');
Additionally, use the following operation to transform strings into date objects:
-
To transform a JavaScript string into an
org.joda.time.DateTimeobject, use aparse()operation with aDateTimeFormattermethod as a parameter:DateTime.parse("04/02/2022 20:27:05", DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss"));
Date and time operations
Use the following expressions in JavaScript code, for example, when defining K-fields or Importers. They assume that a date field called mydate exists and can be referenced. Some expressions also reference a second date called mydate2.
org.joda.time.DateTime. When dealing with a JavaScript Date object or a Java.util.Date object, first transform it into a Joda-Time object by wrapping it in a date() operation. date(myDate).getYear()
Generally, these operations must be placed in the context of a function, like shown in the example below:
(function() {
return mydate.getYear();
})();
Chain operations together by placing a . in between them. Each operation in a chain is evaluated over the result of the previous operation. For example, in the following expression, the plusHours() operation acts upon mydate and adds two hours to it. The isBeforeNow() operation works on the previous result and evaluates if the new date is before the present date, returning True or False.
return mydate.plusHours(2).isBeforeNow();
Date formatting operations
formatDate() function is available for k-fields but not for Importers. a_invite_first_opened_date A-field is deprecated. Instead, use field a_email_invite_first_opened which mimics the obsolete field.The formatDate() operation takes a date and returns it in any notation format, below are a few examples:
| Example Output | Operation |
|---|---|
| 2017-10-18T20:46:24.000-0700 | formatDate(mydate, "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); |
| 8:46 PM, PDT | formatDate(mydate, "K:mm a, z"); |
| Wed, Oct 18, '17 | formatDate(mydate, "EEE, MMM d, ''yy"); |
Date manipulation operations
| Description | Operation |
|---|---|
| Get year from date | mydate.getYear() |
| Get month from date | mydate.getMonthOfYear() |
| Get day of week from date | mydate.getDayOfWeek() |
| Add two days to a date | mydate.plusDays(2) |
Determine if a date hasn't occurred yet (this operation returns True or False) | mydate.isBeforeNow() |
| Get the difference in full 24 hour days between two dates | daysDifferenceBy24Hours(mydate, mydate2) |
daysDifferenceBy24Hours(mydate, mydate2) function is available for k-fields but not for Importers.getYear() is 100 or greater. For example, if the year is 2026, getYear() returns 126. For information about getYear(), see the Mozilla developer reference.Time manipulation operations
| Description | Operation |
|---|---|
| Get the difference in hours between two times | hoursDifference(mydate, mydate2) |
| Convert a time to a different time zone | mydate.withZone(org.joda.time.DateTimeZone.forID('Europe/London') |
| Add two hours to a time | mydate.plusHours(2) |
program_interval = new org.joda.time.Interval(start_date, end_date) to achieve similar results.Tips and considerations
Most often, you should rely on the operations and expressions listed above to define K-fields or Importers. However, some cases might merit a different strategy.
In certain contexts, some Date fields are returned as an array of long integers. For example, see the fields used in the action (particularly e_bp_annual_survey_start_date and e_bp_annual_survey_end_date) in the Omni Exporter event below:
{
"changedEntities" : [ {
"q_bp_portal_survey_firstname_txt" : null,
"q_bp_portal_survey_program_alt" : null,
"q_bp_portal_survey_email_txt" : null,
"q_bp_portal_survey_language_alt" : null,
"a_surveyid" : 336042,
"e_bp_portal_survey_start_date" : [2021,12,2],
"e_bp_portal_survey_end_date" : [2021,12,27]
} ]
}
In this case, Date is internally represented as an array with 3 elements: [yyyy, MM, dd] in the JSON structure. To process this array with a string format, use the following approach:
var fieldToDate = function (field) {
if (!isArray(field)) {
return null;
}
return formatDate(
new Date(
field[0],
field[1] - 1,
field[2]
),
'yyyy-MM-dd'
);
};
The function formatDate() returns a JavaScript Date object, where the initial position in the array represents the year, the second position represents the month, and the third position represents the day of the month.
Common errors
Illegal instant due to timezone offset transition
This usually indicates that a org.joda.time.DateTime operation was used to update an object to a date that does not exist. This is usually because the date falls on a daylight savings time transition.
Change the script to avoid this. For example, use the withMillis() operation to set the date of a org.joda.time.DateTime object while accounting for time shifts. The getMillis() method can be used to get the Unix timestamp of an object, also avoiding this problem. Check the org.joda.time.DateTime documentation for details.
TypeError: Cannot find function [X] in object [Time]
This indicates that an invalid method was used on an object. For example, getHours() will not work on an org.joda.time.DateTime object because that method does not exist for that object type. Reference the object's documentation and use the correct method.
Dates in conditions
When working with import conditions that refer to a period of time, express the time in days months and years as follows:
-
The number of days followed by
d, as in 35d. -
The number of months followed by
m, as in 4m. -
The number of years followed by
y, as in 2y.
So, for example, a condition could refer to the field e_record_creationdate, use the operator Date in last interval and have the value 35d.
