4

We are using SXA Rendering Variants with Scriban for our websites. In order to format the value of Sitecore field type DateTime in Scriban I am using

`{{ sc_field i_item 'Date' [ [ 'format', 'd\nM,\nyyyy' ] ] }}` . 

This works fine if the value is between the tags like below

<module-headline block="text-content">
                    {{ sc_field i_item 'EventDate' [ [ 'format', 'd\nM,\nyyyy' ] ] }}
                  </module-headline>

<!-- OR display: block -->
                  
                  <module-subline>{{ sc_field i_item 'EventDate' [ [ 'format', 'd\nM,\nyyyy' ] ] }}</module-subline>

But if I try to use this in one of the properties of the tags or with in JSON object in Scriban it does not work.

<sticky-detail-module

                    date="{{ sc_field i_item 'EventDate' [ [ 'format', 'd\nM,\nyyyy' ] ] }}"
                    place="{{ chosenevent.EventLocationLong.raw }}"
                    button-url="{{ sc_linktargeturl chosenevent 'Button1' }}"
                    button-text="{{ chosenevent.Button1Text.raw }}"
                  >
                  </sticky-detail-module>

OR WITH

 <events-teaser
                    :events="[
                    {
                      'place':'Barcelona',
                      'date':'{{ sc_field i_item 'EventDate' [ [ 'format', 'd\nM,\nyyyy' ] ] }}',
                      'title':'Headline',
                      'summary':'120 letters description – Lorem ipsum dolor sit amet, consetetur sadipscing elitr.',
                      'image':'../1920x1080.png',
                      'alt':'main events image',
                      'button2Text':'More information',
                      'button1Text':'Buy tickets',
                      'button2Url':'https://www.google.com/',
                      'button1Url':'https://www.google.com/'
                    },
                    {
                      'place':'Barcelona',
                      'date':'{{ sc_field i_item 'EventDate' [ [ 'format', 'd\nM,\nyyyy' ] ] }}',
                      'title':'Headline',
                      'summary':'120 letters description – Lorem ipsum dolor sit amet, consetetur sadipscing elitr.',
                      'image':'../1920x1080.png',
                      'alt':'main events image',
                      'button2Text':'Text 2',
                      'button1Text':'Text 1',
                      'button2Url':'https://www.google.com/',
                      'button1Url':'https://www.google.com/'
                    },
                  ]">
                 </events-teaser>

Is there a way to parse Sitecore DateTime field type value in a particular Date or Time format directly in Scriban for the tag properties as well? Is custom Embedded functions the only way to achieve this formatting?

0

Scriban has some nice date functions built in so you can use those. Unfortunately, Sitecore stores the raw value as yyyMMddThhmmssZ - so 20210709T102600Z for example. This is not a valid format for C#'s DateTime.Parse function, (which is what Scriban uses under the hood). So we need to get a bit sneaky with string parsing.

There are 2 options:

Option 1: No custom functions, Just scriban

Instead of using the field renderer, I would start with the raw value of the date field. Because of the non-standard date format, we need to be inventive in pulling the date out of Sitecore to allow the parsing to happen

eventDateString = (i_item.EventDate.raw | string.slice 0 4) + '-' + (i_item.EventDate.raw | string.slice 4 2) + '-' + (i_item.EventDate.raw | string.slice 6 2)

This will get us a string that looks like: yyyy-MM-dd. Now we can parse that into an actual date object:

eventDate = date.parse eventDateString

Now you can use the .to_string function in scriban to format the date:

formattedDate = eventDate.to_string '%d %m, %Y'

This can be even more simplified to

eventDate = date.parse eventDateString | date.to_string '%d %m, %Y'

The pipe works in a similar way to SPE where the value of the pipe is passed as the first argument in the next call.

Now you can use that variable in your json:

 <events-teaser
    :events="[
        {
          'place':'Barcelona',
          'date':'{{ eventDate }}',
          'title':'Headline',
          'summary':'120 letters description – Lorem ipsum dolor sit amet, consetetur sadipscing elitr.',
          'image':'../1920x1080.png',
          'alt':'main events image',
          'button2Text':'More information',
          'button1Text':'Buy tickets',
          'button2Url':'https://www.google.com/',
          'button1Url':'https://www.google.com/'
        },
    ]">
</events-teaser>

Option 2: Just write an embedded function, its cleaner

Having said all that, its a bit ugly to have to write that in Scriban. Its not reusable and hard to maintain. An embedded function would be simpler. This is one that I commonly have in my projects:

public class GetDateFieldShortDate : IGenerateScribanContextProcessor
{
    private readonly IContext context;
    private delegate string Delegate(Item item, string fieldName);

    public GetDateFieldShortDate(IContext context)
    {
        this.context = context;
    }

    public void Process(GenerateScribanContextPipelineArgs args)
    {
        args.GlobalScriptObject.Import("sc_date_short", new Delegate(GetShortDate));
    }

    public static string GetShortDate(Item item, string fieldName)
    {
        if (item?.Fields[fieldName] == null)
        {
            return string.Empty;
        }

        DateField field = item.Fields[fieldName];
        return field.DateTime.ToShortDateString(); 
    }
}

Is returns the Sitecore formatted date as a ShortDateString which the scriban date.parse function is able to use.

Your scriban now becomes:

eventDate = sc_date_short i_item 'EventDate' | date.parse | date.to_string '%d %m, %Y'

Much much simpler :)

references: If the date format strings look funny... they are, scriban seems to have its own set of format strings for some reason. Details are here: https://github.com/scriban/scriban/blob/486ae53003f3e9775d25a856f80cb28ca3b55e84/src/Scriban/Functions/DateTimeFunctions.cs#L287

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.