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.
<dl class="store-details-hours__list">
{% for item in storeHours %}
<dt class="store-details-hours__day">
{{ item.days|first }}{% if item.days|length > 1 %} - {{ item.days|last }}{% endif %}
</dt>
{% if item.open|length and item.close|length %}
<dd class="store-details-hours__hours" itemprop="openingHours"
content="{{ item.daysShort|join(',') }} {{ item.open|date('h:i') }} - {{ item.close|date('h:i') }}">
{{ item.open|date('h:i a') }} - {{ item.close|date('h:i a') }}
</dd>
{% else %}
<dd class="store-details-hours__hours" itemprop="openingHours"
content="{{ item.daysShort|join(',') }} Closed">
Closed
</dd>
{% endif %}
{% endfor %}
</dl>
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 %}