Date comparison on Events using SSJS and metadata

Matrix Version: latest version

Hello Squiz community,

Has anyone successfully managed to do a date comparison on Events using a related metadata field with SSJS?

What I’m trying to achieve is:

  • Show the event start date.
  • If the end date is greater than the start date, also show the end date.
  • If the end date is the same as the start date, only show the start date.

The output should look something like this:

  1. 25 May 2025 to 26 May 2025
  2. 24 May 2025 (end date is the same as start date, so don’t show it)

Has anyone got an example or approach for handling this logic in SSJS with event metadata?

Thanks in advance and here is a sample:

<script runat="server">
(() => {
const relatedEvents = %asset_metadata_related_assets^json_decode^empty:[]%;

// Helper to format dates
const formatDate = date =>
  date.toLocaleDateString("en-AU", {
    day: "numeric",
    month: "short",
    year: "numeric"
  });

let output = "";

relatedEvents.forEach(eventId => {
  const startDateStr  = "%globals_asset_attribute_start_date:" + eventId + "%";
  const endDateStr   = "%globals_asset_attribute_event_end_date:" + eventId + "%";

  if (!startDateStr) return; // skip if no start date

  const startDate = new Date(startDateStr);
  const endDate   = new Date(endDateStr);

  if (endDateStr && endDate > startDate) {
    output += `<p>${formatDate(startDate)} to ${formatDate(endDate)}</p>`;
  } else {
    output += `<p>${formatDate(startDate)}</p>`;
  }
});

print(output);
})();
</script>

output is invalid date :frowning:

Have you printed the date in your startDateStr & endDateStr to see what format its returned in?

Sounds like they are returning a format that new Date() doesn’t accept (Unix timestamp, dd/m/yyy etc.)

You’ll likely need to write a helper function to format and parse an accepted format in (ISO 8601 or milliseconds since epoch)

Instead of values, global keywords are storing as whole string of keyword(without rendering) in “startDateStr & endDateStr”. You can simply confirm by

print("<p>" + startDateStr .length + "</p>");
print("<p>" + endDateStr.length + "</p>");

Workaround: You can add the following keyword in your events’ metadata field and print it in SSJS. No need for If condition.

%event_end_datetime^date_format:Ymd^gt:{event_start_datetime^date_format:dmY}:to {event_end_datetime^date_format:d F Y}%

Hello Harinder,

I originally tried using the globals namespace inside my loop, but that didn’t work as expected and had me stuck for a while. The fix was to pull the fields into the ^as_asset: call and then normalise them with .map(), giving each property a clean name (e.g. title, dateStartDisplay, dateEndDisplay) etc

Inside the forEach I just destructure the fields I need, check if the end date is different from the start date, and build the markup. This keeps it clean, avoids the confusing globals behaviour, and makes it easy to extend later with description, location, etc.

// Normalise raw data into cleaner objects
const items = rawItems.map(item => ({
    title: item.asset_name,
    dateStartDisplay: item['asset_attribute_start_date^date_format:j F Y'],
    dateEndDisplay: item['asset_attribute_end_date^date_format:j F Y']
}));


items.forEach(item => {
      const { title, 
              dateStartDisplay, 
              dateEndDisplay} = item;

      const showEndDate = dateEndDisplay && dateEndDisplay !== dateStartDisplay;

      listMarkup += `
          <li>
              <strong>${title}</strong><br>
              ${dateStartDisplay}${showEndDate ? ` to ${dateEndDisplay}` : ``}
          </li>
      `;...
1 Like

Thanks Matt, I’ll keep this in mind :slight_smile: