Skip to content

Python: Adjusting for DST from the Canvas API

If you didn’t know, Canvas’ date fields are stored in, and I quote (from the rest api guidance!), “All timestamps are sent and returned in ISO 8601 format. All timestamps default to UTC time zone unless specified.” This info can all be found here: SIS Import Format Documentation

If you don’t know what a UTC timestamp looks like in IOS 8601 format, they look like a bit like this:

2022-12-11T10:32:56Z (YYYY-MM-DDTHH:MM:SSZ)

Now that’s all well and good, but how do you know, if you’re in a country that has daylight time saving that the date from the api needs to be adjusted for daylight time saving (dts)? I stumbled across this lately where I noticed a mix of deadlines that were either spot on or an hour out! This led me down a proverbial rabbit hole of discovery to fix the deadlines, or at least to find out why on earth I was getting what appeared to be an error out of api!

Libraries to import

You will need to import a couple of libraries, nothing heavy, and I also grab today’s date timestamp. You will also need to set the required time zone to check dst. It needs use a timezone-aware datetime object and you need to set the time zone you the one want to check. In our case it’s “Europe/London”. Set that in the code.

from canvasapi import Canvas

import datetime
import pytz
now = datetime.datetime.now()

timeZone = pytz.timezone("Europe/London")

Getting time and date elements in Python

If you don’t how to use the api in python or even don’t use the api from Canvas, get on it, it’s pretty handy. In python, I use the canvasapi library. Its cracking, and with knowledge of how and what to get out it, it’s pretty powerful, This guide won’t go into using canvasapi but do make sure you include the library too using from canvasapi import Canvas as per the code snippet above. So we retrieve the date in the format as above from the api, now you will want to grab each element of it. I split mine like this:

assignment_due_at = assignment.due_at
#contains 2022-12-11T10:32:56Z

if assignment_due_at:
   year = assignment_due_at[0:4]
   day = assignment_due_at[5:7]
   month = assignment_due_at[8:10]
   hour = assignment_due_at[11:13]
   
   #just rounding these two
   minute =  "00"
   second =  "00"

The Function

The code below is the magic function. I can’t take any credit for this, I found it here and it worked a treat! It basically deals with the date, by adding in parameters in the form of this:

def is_dst(dt,timeZone):
   aware_dt = timeZone.localize(dt)
   return aware_dt.dst() != datetime.timedelta(0,0)

It’ll return True or False if the date falls within in the DTS or not. Now that’s pretty cool if I do say so myself! So to now use it with your date elements you grabbed earlier, we do the following:

dt = datetime.datetime(int(lyear),int(lday),int(lmonth),int(lhour),int(lminute),int(lsecond))

Now to check what comes back and to actually do something with it, in our case add an hour to the hour element if its in dst (genius):

if is_dst(dt,timeZone) == True:
  assignment_lock_at = dt + datetime.timedelta(hours=1)

With all of the above if you create a loop to work with your dataset, checking for dst each time you’ll have adjusted the UTC date to your dst or left alone if not in no time.