Store Hours (group days by hours) I'm using the Store Hours plugin to output store hours like this:

{% set days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] %}
{% set daysShort = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] %}

&lt;dl class="store-details-hours__list"&gt;
  {% for dayHours in entry.hoursOfOperation %}
    &lt;dt class="store-details-hours__day"&gt;{{ days[loop.index0] }}&lt;/dt&gt;

    {% if dayHours.open|length and dayHours.close|length %}

      &lt;dd class="store-details-hours__hours"
        itemprop="openingHours" content="{{ daysShort[loop.index0] }} {{ dayHours.open|date('h:i') }} - {{ dayHours.close|date('h:i') }}"&gt;{{ dayHours.open|date('h:i a') }} - {{ dayHours.close|date('h:i a') }}&lt;/dd&gt;
    {% else %}
    &lt;dd class="store-details-hours__hours"
      itemprop="openingHours" content="{{ daysShort[loop.index0] }} Closed"&gt;Closed&lt;/dd&gt;
    {% endif %}
  {% endfor %}

&lt;/dl&gt;


This works okay and outputs like this:



But what I really need is to be able to group the days if the hours are the same so that it looks like this:



It's also important that I can set an attribute tag on the &lt;dd&gt; of content="Mo,Tu,We, 10:00-17:00" So how do I group days of the week and output the hours the way my client wants it to look?
I think I have a solution to this problem, but it's kind of complicated. There may be a way to simplify this more.

The basic idea is to loop thru your Store Hours field (entry.hoursOfOperation) and build a new array (storeHours) where the days are combined if the current loop's open and close times match the previous loop's.

{% set days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] %}
{% set daysShort = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] %}

{# Setup a new array storeHours to hold all you hashes 
   and prev variables to compare things to in the loop 
 #}
{% set storeHours, prevDays, prevDaysShort, prevOpen, prevClose = [],[],[],"","" %}

{# Loop thru your Store Hours field and build the storeHours array #}
{% for item in entry.hoursOfOperation %}

  {# in the first loop, setup the prevOpen and prevClose variables  #}
  {% if loop.first %}
    {% set prevOpen, prevClose = item.open, item.close %}
  {% endif %}

  {# If the prev hours match the current item's hours, 
     add that day's name to the array of prev days, ["Monday","Tuesday"] etc.
   #}
  {% if prevOpen == item.open and prevClose == item.close %}
    {% set prevDays = prevDays|merge([days[loop.index0]]) %}
    {% set prevDaysShort = prevDaysShort|merge([daysShort[loop.index0]]) %}

  {# If it doesn’t match, add prev variables as a hash to the storeHours array,
     Then set all prev variables with current item
   #}
  {% else %}

    {% set storeHours = storeHours|merge([{
      "days" : prevDays,
      "daysShort" : prevDaysShort,
      "open" : prevOpen,
      "close" : prevClose
    }]) %}

    {% set prevDays = [days[loop.index0]] %}
    {% set prevDaysShort = [daysShort[loop.index0]] %}
    {% set prevOpen = item.open %}
    {% set prevClose = item.close %}

  {% endif %}

  {# If last loop, add prev variables as a hash to the storeHours array
     because there won’t be another loop to compare it to.
   #}
  {% if loop.last %}
    {% set storeHours = storeHours|merge([{
      "days" : prevDays,
      "daysShort" : prevDaysShort,
      "open" : prevOpen,
      "close" : prevClose
    }]) %}
  {% endif %}

{% endfor %}


The storeHours data format will be something like this:

[
  {
    "days" : ["Monday", "Tuesday", "Wednesday"],
    "daysShort" : ["Mo","Tu","We"],
    "open" : "2017-01-21 09:30:00.000000",
    "close" : "2017-01-21 21:00:00.000000"
  },
  {
    "days" : ["Thursday","Friday"],
    "daysShort" : ["Th","Fr"],
    "open" : "2017-01-21 09:00:00.000000",
    "close" : "2017-01-21 17:00:00.000000"
  }
]


Once you've created your storeHours array, you can use it to output your HTML code.

&lt;dl class="store-details-hours__list"&gt;
  {% for item in storeHours %}

    &lt;dt class="store-details-hours__day"&gt;
      {{ item.days|first }}{% if item.days|length &gt; 1 %} - {{ item.days|last }}{% endif %}
    &lt;/dt&gt;    

    {% if item.open|length and item.close|length %}
      &lt;dd class="store-details-hours__hours" itemprop="openingHours" 
        content="{{ item.daysShort|join(',') }} {{ item.open|date('h:i') }} - {{ item.close|date('h:i') }}"&gt;
        {{ item.open|date('h:i a') }} - {{ item.close|date('h:i a') }}
      &lt;/dd&gt;
    {% else %}
      &lt;dd class="store-details-hours__hours" itemprop="openingHours" 
        content="{{ item.daysShort|join(',') }} Closed"&gt;
        Closed
      &lt;/dd&gt;
    {% endif %}

  {% endfor %}
&lt;/dl&gt;




BONUS ROUND: if you want to make Monday the first day of the week, reorder the days and daysShort arrays at the top like this:

{% set days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] %}
{% set daysShort = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'] %}


Then add this line just below it:

{% set hoursMondayFirst = entry.hoursOfOperation|slice(1,entry.hoursOfOperation|length)|merge(entry.hoursOfOperation|slice(0,1)) %}


That makes a new variable using Twig's slice filter to take Monday - Saturday (slice(1|length)) and merge Sunday at the end (slice(0,1)).

Now just use this as the start of your loop:

{% for item in hoursMondayFirst %}