Skip to main content

How do I sort on a Calendar field?

A Calendar field's value, distinct from a Date/Time field, is formatted MM-dd-yyyy. Sorting on that string directly doesn't work, so convert it to a numeric timestamp first and sort on a lookup table.

With the XPath Tool

Velocity
#set ($pages = $_XPathTool.selectNodes($contentRoot, "/system-index-block/system-page[system-data-structure[calendar-field != '/']]"))

#if ($pages.size() > 0)
    #set ($lookupTable = [])

    #foreach ($p in $pages)
        #set ($date = $_DateTool.toDate("MM-dd-yyyy", $p.getChild("system-data-structure").getChild("calendar-field").value))
        #set ($dateTimestamp = $date.getTime())
        #set ($_void = $lookupTable.add({
          "timestamp": $_MathTool.mul($dateTimestamp, 1),
          "page": $p
        }))
    #end

    #foreach ($page in $_SortTool.sort($lookupTable, ["timestamp:desc"]))
        #set ($timeStamp = $page.get("timestamp"))
        #set ($item = $page.get("page"))
        #set ($itemDate = $_EscapeTool.xml($item.getChild("system-data-structure").getChild("calendar-field").value))
        #set ($dateFormat = $_DateTool.getDateFormat("MM-dd-yyyy", $_DateTool.getLocale(), $_DateTool.getTimeZone()))
        #set ($itemDate = $dateFormat.parse($itemDate))
        #set ($itemTitle = $_EscapeTool.xml($item.getChild("title").value))

        $_DateTool.format('MM/dd/yyyy', $itemDate) - ${timeStamp} - $itemTitle
    #end
#end

With the Cascade API

Velocity
#set ($pages = $_.query().byContentType("path/to/Content Type").execute())
#set ($removed = $_ListTool.removeNull($pages, "structuredDataNode(calendar-field).textValue"))

#if ($pages.size() > 0)
    #set ($lookupTable = [])

    #foreach ($p in $pages)
        #set ($date = $_DateTool.toDate("MM-dd-yyyy", $p.getStructuredDataNode("calendar-field").textValue))
        #set ($dateTimestamp = $date.getTime())
        #set ($_void = $lookupTable.add({
          "timestamp": $_MathTool.mul($dateTimestamp, 1),
          "page": $p
        }))
    #end

    #foreach ($page in $_SortTool.sort($lookupTable, ["timestamp:desc"]))
        #set ($timeStamp = $page.get("timestamp"))
        #set ($item = $page.get("page"))

        $item.getStructuredDataNode("calendar-field").textValue - ${timeStamp} - $item.metadata.title
    #end
#end

Note the removeNull call in the API example — pages without a Calendar value would otherwise break the sort. See Comparison method violates its general contract for what that failure looks like.