Skip to content

Instantly share code, notes, and snippets.

@aknosis
Created October 22, 2012 15:52
  • Star 38 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save aknosis/3932192 to your computer and use it in GitHub Desktop.
Table based calendar only using Twig
{#
time can be any string acceptable by http://www.php.net/strtotime, the
template will output that time's month.
If you don't want to pass in a date you can set time like this:
{% set time = "now"|date("U") %}
{% set time = "December 2012"|date("U") %}
How ever you want to output items onto the calendar is a different issue,
but I'd assume pushing everything into an array numerically indexed by that day:
$days = array(1=>array('Something on the first'),31=>array('Halloween'));
#}
<table>
<thead>
<tr>
<th colspan="7" class="center">
{{ time|date('F') }}
</th>
</tr>
<tr>
<th width="12%">Sunday</th>
<th width="15%">Monday</th>
<th width="15%">Tuesday</th>
<th width="16%">Wednesday</th>
<th width="15%">Thursday</th>
<th width="15%">Friday</th>
<th width="12%">Saturday</th>
</tr>
</thead>
<tbody>
<tr>
{% set daysInMonth = time|date('t') %}
{% set startDow = time|date('F 1\\s\\t Y')|date('w') %}
{% set dow = startDow %}
{% for day in range(1,daysInMonth) %}
{% if loop.first and startDow != 0 %}
<td colspan="{{ startDow }}"></td>
{% endif %}
<td>
<div>
<div>{{ day }}</div>
<div>
{# day content here #}
</div>
</div>
</td>
{% if loop.last and dow != 6 %}
<td colspan="{{ 6 - dow }}">&nbsp;</td>
{% endif %}
{% if dow == 6 %}
{% set dow = 0 %}
</tr>
<tr>
{% else %}
{% set dow = dow + 1 %}
{% endif %}
{% endfor %}
</tr>
</tbody>
</table>
@vtedesco
Copy link

vtedesco commented May 2, 2015

nice

@daler-als
Copy link

Sorry for the stupid question, but how to start a week from Monday instead Sunday?

@youmad
Copy link

youmad commented Jun 26, 2015

how to start a week from Monday instead Sunday?

L22-L28:

            <tr>
                <th width="15%">Monday</th>
                <th width="15%">Tuesday</th>
                <th width="16%">Wednesday</th>
                <th width="15%">Thursday</th>
                <th width="15%">Friday</th>
                <th width="12%">Saturday</th>
                <th width="12%">Sunday</th>
            </tr>

L34:

            {% set startDow = time|date('F 1\\s\\t Y')|date('N') - 1 %}

@kalebheitzman
Copy link

Excellent!

@websemantics
Copy link

Saved me few hours trying to figure it out ..
Thanks for sharing,

@tompiard
Copy link

Simple and efficient, thanks !

@boubouhkarim
Copy link

Thanks, you saved my time.

@aknosis
Copy link
Author

aknosis commented Sep 24, 2017

Totally forgot I wrote this. Glad people found it useful.

@jasongabler
Copy link

jasongabler commented Jan 17, 2018

This is great! Well done. What a time saver.

Here's an example of how I used your code, w/ Bootstrap and daily activity data collated by $activityByDay[year][month][day]. The value for a given day (in my case) is an array of objects for building information, links, etc. to display within that day's box in the calendar.

    {% for year,months in activityByDay %}
        {% for month, days in months %}
            {% set execution = days|first|first %}
            {% set time = execution.actionStamp|date("U") %}
            <table class="table table-bordered">
                <thead>
                <tr class="month-name">
                    <th colspan="7" class="text-center">{{ time|date('F Y') }}</th>
                </tr>
                <tr class="week-name">
                    <th>Sunday</th>
                    <th>Monday</th>
                    <th>Tuesday</th>
                    <th>Wednesday</th>
                    <th>Thursday</th>
                    <th>Friday</th>
                    <th>Saturday</th>
                </tr>
                </thead>
                <tbody>
                <tr>
                    {% set daysInMonth = time|date('t') %}
                    {% set startDow = time|date('F 1\\s\\t Y')|date('w') %}
                    {% set dow = startDow %}
                    {% for day in range(1,daysInMonth) %}
                        {% if loop.first and startDow != 0 %}
                        <td colspan="{{ startDow }}"></td>
                        {% endif %}
                        <td>
                            <div>
                                <div>{{ day }}</div>
                                <div class="day">
                                    {% if days[day] is defined %}
                                        {% for activity in days[day] %}
                                            <a href="{{ path('activity_page', {'activityId':activity.id}) }}">{{ activity.name }}</a><br>
                                        {% endfor %}
                                    {% endif %}
                                </div>
                            </div>
                        </td>
                        {% if loop.last and dow != 6 %}
                            <td colspan="{{ 6 - dow }}">&nbsp;</td>
                        {% endif %}
                        {% if dow == 6 %}
                        {% set dow = 0 %}
                        </tr>
                        <tr>
                        {% else %}
                            {% set dow = dow + 1 %}
                        {% endif %}
                    {% endfor %}
                </tr>
                </tbody>
            </table>
        {% endfor %}
    {% endfor %}

@luger95
Copy link

luger95 commented Jun 18, 2018

For some months, we end up with emptiness. Do you have a solution ?

@AlexandreGagner
Copy link

You need to create a repo for this ! 😍
@luger95 I'm making the version with previous day of month at start, and day of after month for the end. Si tu veux.

@scottsawyer
Copy link

scottsawyer commented Apr 6, 2019

This helped me so much! I wanted to use flexbox instead of a table, and I wanted to print all of the empty cells, so I made the following changes:

<main id="bus-availability-calendar">
    <section class="th">
        <span>Sunday</span>
        <span>Monday</span>
        <span>Tuesday</span>
        <span>Wednesday</span>
        <span>Thursday</span>
        <span>Friday</span>
        <span>Saturday</span>
    </section>
    <div class="week">
      {% set daysInMonth = time|date('t') %}
      {% set startDow = time|date('F 1\\s\\t Y')|date('w') %}
      {% set dow = startDow %}
      {% for day in range(1, daysInMonth) %}
        {% if loop.first and startDow != 0 %}
          {% for days in 1..startDow %}
            <div class="day empty"></div>
          {% endfor %}
        {% endif %}
        <div class="day has-entry">
          <div>
            <div class="day-label-wrapper"><span class="day-label" title="{{ time|date('F d, Y') }}">{{ day }}</span></div>
            <div class="day-content-wrapper">
              {% for key, events in events %}
                {% if key  == day %}
                  <div class="event">
                    {{ event }}
                  </div>
                {% endif %}
              {% endfor %}
            </div>
          </div>
        </div>
        {% if loop.last and dow != 6 %}
          {% for days in dow..5 %}
            <div class="day empty"></div>
          {% endfor %}
        {% endif %}
        {% if dow == 6 %}
          {% set dow = 0 %}
          </div><!-- end week -->
          <div class="week">
        {% else %}
          {% set dow = dow + 1 %}
        {% endif %}
      {% endfor %}        
    </div>
</main>

This prints empty cells at the beginning and end, and prints events ( keyed by day ). Added some CSS classes to make it easier to style.

@qroft
Copy link

qroft commented Nov 27, 2020

Would be awesome if some of you could show their JSON/Array structure for the key,value data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment