Shifting dates and times when resetting a Moodle course
When resetting a Moodle course for a new year/semester, it can be very tedious to update the availability and due dates for all activities/assignments/etc in the course. Moodle (supposedly) provides a convenient way to do this:
NOTE: If you set a new course start date, then all course dates will be shifted by the same amount.
Goal
For example, suppose that the old course start date (and time) is set to 14.02.2024 10:00 and activity’s availability/due date (and time) is 14.02.2024 12:00 (i.e. 2 hours after the course start). Both intuitively and according to the quoted documentation, the new course start date should be 12.02.2025 10:00 if the same activity’s date should become 12.02.2025 12:00 (i.e. shifted forward by 2 days less than 1 year).
Problem
Unfortunately (and unsurprisingly), Moodle is not intuitive nor properly documented. If you actually reset the course and choose 12.02.2025 10:00 as the new start date, then the same activity’s date becomes 12.02.2025 22:00 (note the incorrect hour).
Good luck figuring out why! Also, it’s not so easy to just try again by offsetting the new start date, because resetting changed the old start state. This offers hours of fun trial and error just to reset a Moodle course.
Code
Alternatively, one can dig into Moodle source code (something every teacher using Moodle definitely can/wants to do) and eventually find the corresponding logic in moodlelib.php
:
// Time part of course startdate should be zero.
$data->timeshift = $data->reset_start_date - usergetmidnight($data->reset_start_date_old);
For some reason which is completely beyond me,1 the date (and time) shift is not calculated using the old course start date directly. Instead, the usergetmidnight
changes the old 14.02.2024 10:00 into 14.02.2024 00:00 (note the midnight hour) before calculating the difference (with the new course start date that still has user-set hour). In this case, that causes the shift to be 10 hours greater, causing the activity’s date to be shifted 10 hours later.
This means that the undesired extra time shift depends on the old course start time instead of being constant. If it were the latter (e.g. because of some timezone issue), then it would be much simpler to compensate for by trial and error.
According to git blame
, that midnight calculation has been there for 17 years! It took 12 years for anyone to complain in a Moodle issue (MDL-65233), but has been repeatedly reported since (MDL-76882, MDL-82206, …). I wonder how many more years it will take to get fixed.
Fixed
The answer is one month! I went ahead and submitted a patch to remove the
usergetmidnight
. It was accepted by Moodle developers and the fix should ship in Moodle versions 4.4.7 and 4.5.3. Nevertheless, I suggest following the recommended workaround below until you can be sure that your institution has updated.
Workaround
Anyone who has a course to run cannot wait, so here are a few workarounds, illustrated on the example.
Workaround 1
- Reset the course to have new start date 12.02.2025 00:00 (the 10 hours less from the time part of the old start date). The activity’s date will get shifted as intended.
- The course start date after the reset will have the wrong time, so change it to 12.02.2025 10:00 in course settings (not by resetting the course!).
Workaround 2 (recommended)
- Change the old course start date to 14.02.2024 00:00 in course settings (not by resetting the course!). Already having the time be midnight cancels the weirdness of
usergetmidnight
. - Reset the course to have new start date 12.02.2025 00:00 (also midnight). Both the new course start date and activity’s date will be as intended.
This workaround is a bit more future-proof:
- By always having the course start date at midnight, you hopefully avoid the issue during future course resets because the time shift will be intuitive then.
- If
Moodle ever fixes the calculation (to removeyour institution finally updates Moodle, then this does not impact your course resetting workflow. (With workaround 1 you’d have to know about the change and stop manually compensating on each reset, because then you’d be overcompensating.)usergetmidnight
) and
-
Comment below if you think this makes any sense or have any idea why this would ever be desirable. ↩