<p>The important question is how often the schedules of individual tutors change – updating the schedules every night is a lot of work, so I'd try to make it as streamlined as possible.</p>
<h2>If the schedules don't change often …</h2>
<p>… keep the information in the tutors structure. For example, let's say most teachers are always available during the same timeslots every week. Then you could create a checkbox with 14 options (morning and evening for each day of the week respectively) and add it to the tutor entry type. Then you can use that to display the current schedule dynamically. There's only a need for manual intervention if the schedule changes. You could even build a <a href="https://craftcms.com/knowledge-base/front-end-user-accounts" rel="nofollow noreferrer">simple login form</a> for your teachers and allow them to edit their own schedules!</p>
<p>There are variations on this, depending on requirements. For example, if the schedules aren't regular, but teachers generally know their schedule for a couple of weeks or months in advance. Then you can also build a structure (for example, a Matrix or Super Table field) to set schedules for weeks in advance. That's a bit more work, but would allow your client to do the scheduling for everyone a couple of weeks in advance and go on vacation …</p>
<h2>If the schedules change freqently …</h2>
<p>… you want a central place to select the available teachers for each day. A global set with four entries fields (evening and night for today and tommorow respectively) would be an option. But keep in mind that this makes it  impossible to create a schedule for more than one day in advance. Also, you'd have to move the entries from the &quot;tomorrow&quot; fields to the &quot;today&quot; fields every evening, and this won't be accurate unless your client updates the schedule precisely at midnight.</p>
<p>I'd still prefer some structure where it's possible to set schedules in advance. How about having a channel for the schedule, where each entry contains the available tutors for one day as two entries fields (for morning and evening, respectively). Each entry corresponds to the day of it's <code>postDate</code> (maybe use a custom entry save hook to prevent more than one entry per day). This will allow your client to create schedules in advance if they want to, and you also get data on past schedules if you ever need it.</p>
<p>Keep in mind that you have to query for entries with status <code>pending</code> if you want to get entries with a <code>postDate</code> in the future:</p>
<pre class="lang-twig prettyprint-override"><code>{% set scheduleEntries = craft.entries().section('schedule').status(['live', 'pending']).all() %}
</code></pre>
<h3>Implementation details</h3>
<p>To address the comments: You can do a lot of validation and custom adjustments using <a href="https://craftcms.com/knowledge-base/handling-entry-saves" rel="nofollow noreferrer">entry save hooks</a>. For the approach above (a <code>schedule</code> channel with one entry per day), I would use a hook to prevent multiple schedule entries with a <code>postDate</code> on the same day:</p>
<ol>
<li>Add an <code>Entry::EVENT_BEFORE_SAVE</code> hook in a site module.</li>
<li>For <code>schedule</code> entries, check the <code>postDate</code> and use an element query to find if there already any <code>schedule</code> entries that day (between midnight and midnight).</li>
<li>If there are, prevent the save using <code>$event-&gt;isValid = false</code> and display an error (maybe using <code>$entry-&gt;addError('postDate', '...')</code>, not sure if the interface supports it, otherwise you can use a flash message).</li>
</ol>
<p>You can also force the <code>postDate</code> to midnight or noon for consistency if you like, but it doesn't really matter if you're only checking for the day of the <code>postDate</code>.</p>
<blockquote>
<p>How would you filter out the other schedule entries and only select one for today and only one for tomorrow?</p>
</blockquote>
<p>You can do that with an entry query with a parameter limiting the query to entries with a postDate between the previous and next midnight (and the same for the next day, respecively).</p>
<pre class="lang-php prettyprint-override"><code>$today = new \DateTimeImmutable('today');
$tomorrow = $today-&gt;modify('+1 day');
$dayAfterTomorrow = $tomorrow-&gt;modify('+1 day');

$scheduleQuery = Entry::find()-&gt;section('schedule');
$todaySchedule = clone($scheduleQuery)-&gt;postDate([
    'and',
    &quot;&gt;={$today-&gt;getTimestamp()}&quot;,
    &quot;&lt;={$tomorrow-&gt;getTimestamp()}&quot;
])-&gt;one();
$tomorrowSchedule = clone($scheduleQuery)-&gt;postDate([
    'and',
    &quot;&gt;={$tomorrow-&gt;getTimestamp()}&quot;,
    &quot;&lt;={$dayAfterTomorrow-&gt;getTimestamp()}&quot;
])-&gt;one();
</code></pre>
<p>Keep in mind that both queries might return <code>null</code> if there isn't a schedule for that particular day, which should be handled accordingly in the interface.</p>
<p>No guarantes regarding the DateTime formats above, I always get those mixed up :) Might also need some special handling for the timezone and/or use UTC, not sure how craft stores it's postDate. But you get the general idea.</p>
<p>I used PHP since the DateTime stuff is a bit easier there, but you can do the same thing in Twig. Or put it in a reusable function to get today's (tomorrow's) schedule and make it available to Twig using a <a href="https://craftcms.com/docs/3.x/extend/extending-twig.html" rel="nofollow noreferrer">Twig extension</a>.</p>

CC BY-SA 4.0
2021-10-29T17:56:04.570Z
Thank you so much for this very thought-out answer! It's nice to see someone else's point of view on this. I think that because my client said the schedules change frequently, you last solution is the best. I would have never thought of doing it with a channel for the daily work shifts. How would you filter out the other schedule entries and only select one for today and only one for tomorrow? Would you simply put the post date for the day of at 12AM?
mateostabio
CC BY-SA 4.0
2021-10-31T14:53:04.600Z
@mateostabio Good questions, I added a section addressing the implementation deatils in my answer! I would just use a hook to ensure only one schedule entry per day. Forcing the postDate to 12 AM (PM?) is possible but not necessary in my opinion.
MoritzLost
CC BY-SA 4.0
2021-10-29T15:26:09.027Z
2021-10-31T14:50:40.143Z
2021-10-31T14:50:40.143Z
MoritzLost
<p>I have built a website showing a list of teachers/tutors (Structure entries). My client now wants to have a way for visitors to see which tutors are available today (morning or evening) and tomorrow (morning or evening). It's not a full-week schedule but it still has 4 options. He says he will be doing the manual work himself every night, updating the tutors' schedules.</p>
<p>I'm a bit lost at how to approach this.</p>
<ul>
<li>Do I create a global field for each work shift and just let him select the tutors with an entries field?</li>
<li>Do I create 4 lightswitch fields tutor entry fields, but then he would have to go and edit every individual tutor entry? Seems like the right choice but longer to modify.</li>
</ul>
<p>How would you approach this? Is there a much better way to do this?</p>

<calendar>
How to create a simple (Today and Tomorrow) schedule?
# How to create a simple (Today and Tomorrow) schedule?

(Asked by: username_0 on 2021-10-29)

I have built a website showing a list of teachers/tutors (Structure entries). My client now wants to have a way for visitors to see which tutors are available today (morning or evening) and tomorrow (morning or evening). It's not a full-week schedule but it still has 4 options. He says he will be doing the manual work himself every night, updating the tutors' schedules.

I'm a bit lost at how to approach this.

* Do I create a global field for each work shift and just let him select the tutors with an entries field?
* Do I create 4 lightswitch fields tutor entry fields, but then he would have to go and edit every individual tutor entry? Seems like the right choice but longer to modify.

How would you approach this? Is there a much better way to do this?

**Tags:** calendar


---

## 1 answers

### Answer by username_1 on 2021-10-29. Score: 3 | Accepted answer

The important question is how often the schedules of individual tutors change – updating the schedules every night is a lot of work, so I'd try to make it as streamlined as possible.
If the schedules don't change often …
… keep the information in the tutors structure. For example, let's say most teachers are always available during the same timeslots every week. Then you could create a checkbox with 14 options (morning and evening for each day of the week respectively) and add it to the tutor entry type. Then you can use that to display the current schedule dynamically. There's only a need for manual intervention if the schedule changes. You could even build a simple login form for your teachers and allow them to edit their own schedules!
There are variations on this, depending on requirements. For example, if the schedules aren't regular, but teachers generally know their schedule for a couple of weeks or months in advance. Then you can also build a structure (for example, a Matrix or Super Table field) to set schedules for weeks in advance. That's a bit more work, but would allow your client to do the scheduling for everyone a couple of weeks in advance and go on vacation …
If the schedules change freqently …
… you want a central place to select the available teachers for each day. A global set with four entries fields (evening and night for today and tommorow respectively) would be an option. But keep in mind that this makes it  impossible to create a schedule for more than one day in advance. Also, you'd have to move the entries from the "tomorrow" fields to the "today" fields every evening, and this won't be accurate unless your client updates the schedule precisely at midnight.
I'd still prefer some structure where it's possible to set schedules in advance. How about having a channel for the schedule, where each entry contains the available tutors for one day as two entries fields (for morning and evening, respectively). Each entry corresponds to the day of it's postDate (maybe use a custom entry save hook to prevent more than one entry per day). This will allow your client to create schedules in advance if they want to, and you also get data on past schedules if you ever need it.
Keep in mind that you have to query for entries with status pending if you want to get entries with a postDate in the future:
{% set scheduleEntries = craft.entries().section('schedule').status(['live', 'pending']).all() %}

Implementation details
To address the comments: You can do a lot of validation and custom adjustments using entry save hooks. For the approach above (a schedule channel with one entry per day), I would use a hook to prevent multiple schedule entries with a postDate on the same day:

Add an Entry::EVENT_BEFORE_SAVE hook in a site module.
For schedule entries, check the postDate and use an element query to find if there already any schedule entries that day (between midnight and midnight).
If there are, prevent the save using $event->isValid = false and display an error (maybe using $entry->addError('postDate', '...'), not sure if the interface supports it, otherwise you can use a flash message).

You can also force the postDate to midnight or noon for consistency if you like, but it doesn't really matter if you're only checking for the day of the postDate.

How would you filter out the other schedule entries and only select one for today and only one for tomorrow?

You can do that with an entry query with a parameter limiting the query to entries with a postDate between the previous and next midnight (and the same for the next day, respecively).
$today = new \DateTimeImmutable('today');
$tomorrow = $today->modify('+1 day');
$dayAfterTomorrow = $tomorrow->modify('+1 day');

$scheduleQuery = Entry::find()->section('schedule');
$todaySchedule = clone($scheduleQuery)->postDate([
    'and',
    ">={$today->getTimestamp()}",
    "<={$tomorrow->getTimestamp()}"
])->one();
$tomorrowSchedule = clone($scheduleQuery)->postDate([
    'and',
    ">={$tomorrow->getTimestamp()}",
    "<={$dayAfterTomorrow->getTimestamp()}"
])->one();

Keep in mind that both queries might return null if there isn't a schedule for that particular day, which should be handled accordingly in the interface.
No guarantes regarding the DateTime formats above, I always get those mixed up :) Might also need some special handling for the timezone and/or use UTC, not sure how craft stores it's postDate. But you get the general idea.
I used PHP since the DateTime stuff is a bit easier there, but you can do the same thing in Twig. Or put it in a reusable function to get today's (tomorrow's) schedule and make it available to Twig using a Twig extension.

> **Comments:**
> **username_0**: Thank you so much for this very thought-out answer! It's nice to see someone else's point of view on this. I think that because my client said the schedules change frequently, you last solution is the best. I would have never thought of doing it with a channel for the daily work shifts. How would you filter out the other schedule entries and only select one for today and only one for tomorrow? Would you simply put the post date for the day of at 12AM?  
> **username_1**: @username_0 Good questions, I added a section addressing the implementation deatils in my answer! I would just use a hook to ensure only one schedule entry per day. Forcing the postDate to 12 AM (PM?) is possible but not necessary in my opinion.  

---

