dateformataemsightlyhtl

Date type required in AEM HTL / Sightly date formatter


I've seen that since AEM 6.3, date formatting has been natively supported in the markup, like so:

${ 'dd~MMMM-yyyy' @ format=currentPage.jcr:created }

(Reference: https://github.com/adobe/htl-spec/blob/master/SPECIFICATION.md#1222-dates )

I have tried playing with this formatter using that jcr:created property, as well as data coming from the backend in java.util.Date.

My question is, are other date types supported? Like say, java.time.LocalDate? It doesn't display on my test pages, although I'm not sure if I'm just missing some additional property that needs to be indicated on the HTL markup?


Solution

  • It's not mentioned in the documentation as far as I can tell but Apache Sling is an open source project so we can look it up on our own.

    Looking at the implementation details, the only supported types as of now are java.util.Date and java.util.Calendar and their sub-classes.

    Here's the FormatFilterExtension class responsible for applying the chosen format in HTL.

    Let's have a look at the check it performs.

     } else if (DATE_FORMAT_TYPE.equals(formattingType) || (!hasPlaceHolders && runtimeObjectModel.isDate(formatObject))) {
          Locale locale = getLocale(runtimeObjectModel, options);
          TimeZone timezone = getTimezone(runtimeObjectModel, options);
          return formatDate(source, runtimeObjectModel.toDate(formatObject), locale, timezone);
     }
    

    It uses runtimeObjectModel.isDate() to verify if we're dealing with a date. If we look at runtimeObjectModel, we can see that it's an instance of SlingRuntimeObjectModel which in turn extends AbstractRuntimeModel.

    @Override
    public boolean isDate(Object target) {
        return (target instanceof Date || target instanceof Calendar);
    }
    

    so if it's a Date or a Calendar, it will be handled.

    Even if you force the formatting type like this

    ${'yyyy-MM-dd' @ format=myDate, type='date'} <!--/* Forced formatting type */-->
    

    the object you pass will end up being processed using AbstractRuntimeObjectModel#toDate(Object object) which returns null for all objects that aren't instances of Date or Calendar.

    Since the check is based on instanceof, this also includes instances of Date and Calendar's sub-types. LocalDate, however, is not one of them so it's not surprising that it didn't work.