We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Document date_filter parameter for timetable endpoint
**Is your feature request related to a problem? Please describe.**

The /timetable/personal endpoint accepts an undocumented `date_filter` query parameter in ISO 8601 format, i.e. YYYY-MM-DD

**Describe the solution you'd like**

Document this in uclapi.com/docs

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `backend/uclapi/timetable/views.py`
Content:
```
1 from distutils.util import strtobool
2 from django.conf import settings
3 
4 
5 from rest_framework.decorators import api_view
6 
7 from common.helpers import PrettyJsonResponse as JsonResponse
8 
9 from .models import Course
10 
11 from .app_helpers import (
12     get_custom_timetable,
13     get_departmental_modules,
14     get_departments,
15     get_student_timetable,
16     get_course_modules,
17     validate_amp_query_params
18 )
19 
20 from common.decorators import uclapi_protected_endpoint
21 
22 _SETID = settings.ROOMBOOKINGS_SETID
23 
24 
25 @api_view(["GET"])
26 @uclapi_protected_endpoint(
27     personal_data=True,
28     required_scopes=['timetable'],
29     last_modified_redis_key='gencache'
30 )
31 def get_personal_timetable_endpoint(request, *args, **kwargs):
32     """
33     Returns a personal timetable of a user. Requires OAuth permissions.
34     """
35     token = kwargs['token']
36     user = token.user
37     try:
38         date_filter = request.GET["date_filter"]
39         timetable = get_student_timetable(user.employee_id, date_filter)
40     except KeyError:
41         timetable = get_student_timetable(user.employee_id)
42 
43     response = {
44         "ok": True,
45         "timetable": timetable
46     }
47     return JsonResponse(response, custom_header_data=kwargs)
48 
49 
50 @api_view(["GET"])
51 @uclapi_protected_endpoint(
52     last_modified_redis_key='gencache'
53 )
54 def get_modules_timetable_endpoint(request, *args, **kwargs):
55     """
56     Returns a timetabe for a module or set of modules.
57     """
58     module_ids = request.GET.get("modules")
59     if module_ids is None or module_ids == '':
60         response = JsonResponse({
61             "ok": False,
62             "error": "No module IDs provided."
63         }, custom_header_data=kwargs)
64         response.status_code = 400
65         return response
66 
67     modules = module_ids.split(',')
68 
69     date_filter = request.GET.get("date_filter")
70     custom_timetable = get_custom_timetable(modules, date_filter)
71 
72     if custom_timetable:
73         response_json = {
74             "ok": True,
75             "timetable": custom_timetable
76         }
77         return JsonResponse(response_json, custom_header_data=kwargs)
78     else:
79         response_json = {
80             "ok": False,
81             "error": "One or more invalid Module IDs supplied."
82         }
83         response = JsonResponse(response_json, custom_header_data=kwargs)
84         response.status_code = 400
85         return response
86 
87 
88 @api_view(["GET"])
89 @uclapi_protected_endpoint(
90     last_modified_redis_key='gencache'
91 )
92 def get_departments_endpoint(request, *args, **kwargs):
93     """
94     Returns all departments at UCL
95     """
96     departments = {
97         "ok": True,
98         "departments": get_departments()
99     }
100     return JsonResponse(departments, custom_header_data=kwargs)
101 
102 
103 @api_view(["GET"])
104 @uclapi_protected_endpoint(
105     last_modified_redis_key='gencache'
106 )
107 def get_department_courses_endpoint(request, *args, **kwargs):
108     """
109     Returns all the courses in UCL with relevant ID
110     """
111     try:
112         department_id = request.GET["department"]
113     except KeyError:
114         response = JsonResponse({
115             "ok": False,
116             "error": "No department ID provided."
117         }, custom_header_data=kwargs)
118         response.status_code = 400
119         return response
120 
121     courses = {"ok": True, "courses": []}
122     for course in Course.objects.filter(owner=department_id,
123                                         setid=_SETID,
124                                         linkcode="YY"):
125         courses["courses"].append({
126             "course_name": course.name,
127             "course_id": course.courseid,
128             "years": course.numyears
129         })
130     return JsonResponse(courses, custom_header_data=kwargs)
131 
132 
133 @api_view(["GET"])
134 @uclapi_protected_endpoint(
135     last_modified_redis_key='gencache'
136 )
137 def get_department_modules_endpoint(request, *args, **kwargs):
138     """
139     Returns all modules taught by a particular department.
140     """
141     try:
142         department_id = request.GET["department"]
143     except KeyError:
144         response = JsonResponse({
145             "ok": False,
146             "error": "Supply a Department ID using the department parameter."
147         }, custom_header_data=kwargs)
148         response.status_code = 400
149         return response
150 
151     modules = {
152         "ok": True,
153         "modules": get_departmental_modules(department_id)
154     }
155 
156     return JsonResponse(modules, custom_header_data=kwargs)
157 
158 
159 @api_view(["GET"])
160 @uclapi_protected_endpoint(
161     last_modified_redis_key='timetable_gencache'
162 )
163 def get_course_modules_endpoint(request, *args, **kwargs):
164     """
165     Returns all modules taught on a particular course.
166     """
167     try:
168         course_id = request.GET["course"]
169     except KeyError:
170         response = JsonResponse({
171             "ok": False,
172             "error": "No course ID provided."
173         }, custom_header_data=kwargs)
174         response.status_code = 400
175         return response
176 
177     if not validate_amp_query_params(request.query_params):
178         response = JsonResponse({
179             "ok": False,
180             "error": "Given parameter is not of corrrect type"
181         }, custom_header_data=kwargs)
182         response.status_code = 400
183         return response
184 
185     if request.query_params.get('only_compulsory'):
186         try:
187             strtobool(request.query_params.get('only_compulsory'))
188         except ValueError:
189             response = JsonResponse({
190                 "ok": False,
191                 "error": "Given parameter is not of correct type"
192             }, custom_header_data=kwargs)
193             response.status_code = 400
194             return response
195 
196     if request.query_params.get('only_available'):
197         try:
198             strtobool(request.query_params.get('only_available'))
199         except ValueError:
200             response = JsonResponse({
201                 "ok": False,
202                 "error": "Given parameter is not of correct type"
203             }, custom_header_data=kwargs)
204             response.status_code = 400
205             return response
206 
207     if (request.query_params.get('only_available') and
208             request.query_params.get('only_compulsory')):
209         if (strtobool(request.query_params.get('only_available')) and
210                 strtobool(request.query_params.get('only_compulsory'))):
211             response = JsonResponse({
212                 "ok": False,
213                 "error": "only_available and only_compulsory"
214                          " cannot both be true"
215             }, custom_header_data=kwargs)
216             response.status_code = 400
217             return response
218 
219     modules = {
220         "ok": True,
221         "modules": get_course_modules(course_id, request.query_params)
222     }
223 
224     return JsonResponse(modules, custom_header_data=kwargs)
225
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/backend/uclapi/timetable/views.py b/backend/uclapi/timetable/views.py
--- a/backend/uclapi/timetable/views.py
+++ b/backend/uclapi/timetable/views.py
@@ -34,11 +34,8 @@
     """
     token = kwargs['token']
     user = token.user
-    try:
-        date_filter = request.GET["date_filter"]
-        timetable = get_student_timetable(user.employee_id, date_filter)
-    except KeyError:
-        timetable = get_student_timetable(user.employee_id)
+    date_filter = request.GET.get("date")
+    timetable = get_student_timetable(user.employee_id, date_filter)
 
     response = {
         "ok": True,
@@ -66,7 +63,7 @@
 
     modules = module_ids.split(',')
 
-    date_filter = request.GET.get("date_filter")
+    date_filter = request.GET.get("date")
     custom_timetable = get_custom_timetable(modules, date_filter)
 
     if custom_timetable:

{"golden_diff": "diff --git a/backend/uclapi/timetable/views.py b/backend/uclapi/timetable/views.py\n--- a/backend/uclapi/timetable/views.py\n+++ b/backend/uclapi/timetable/views.py\n@@ -34,11 +34,8 @@\n     \"\"\"\n     token = kwargs['token']\n     user = token.user\n-    try:\n-        date_filter = request.GET[\"date_filter\"]\n-        timetable = get_student_timetable(user.employee_id, date_filter)\n-    except KeyError:\n-        timetable = get_student_timetable(user.employee_id)\n+    date_filter = request.GET.get(\"date\")\n+    timetable = get_student_timetable(user.employee_id, date_filter)\n \n     response = {\n         \"ok\": True,\n@@ -66,7 +63,7 @@\n \n     modules = module_ids.split(',')\n \n-    date_filter = request.GET.get(\"date_filter\")\n+    date_filter = request.GET.get(\"date\")\n     custom_timetable = get_custom_timetable(modules, date_filter)\n \n     if custom_timetable:\n", "issue": "Document date_filter parameter for timetable endpoint\n**Is your feature request related to a problem? Please describe.**\r\n\r\nThe /timetable/personal endpoint accepts an undocumented `date_filter` query parameter in ISO 8601 format, i.e. YYYY-MM-DD\r\n\r\n**Describe the solution you'd like**\r\n\r\nDocument this in uclapi.com/docs\n", "before_files": [{"content": "from distutils.util import strtobool\nfrom django.conf import settings\n\n\nfrom rest_framework.decorators import api_view\n\nfrom common.helpers import PrettyJsonResponse as JsonResponse\n\nfrom .models import Course\n\nfrom .app_helpers import (\n    get_custom_timetable,\n    get_departmental_modules,\n    get_departments,\n    get_student_timetable,\n    get_course_modules,\n    validate_amp_query_params\n)\n\nfrom common.decorators import uclapi_protected_endpoint\n\n_SETID = settings.ROOMBOOKINGS_SETID\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    personal_data=True,\n    required_scopes=['timetable'],\n    last_modified_redis_key='gencache'\n)\ndef get_personal_timetable_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns a personal timetable of a user. Requires OAuth permissions.\n    \"\"\"\n    token = kwargs['token']\n    user = token.user\n    try:\n        date_filter = request.GET[\"date_filter\"]\n        timetable = get_student_timetable(user.employee_id, date_filter)\n    except KeyError:\n        timetable = get_student_timetable(user.employee_id)\n\n    response = {\n        \"ok\": True,\n        \"timetable\": timetable\n    }\n    return JsonResponse(response, custom_header_data=kwargs)\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    last_modified_redis_key='gencache'\n)\ndef get_modules_timetable_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns a timetabe for a module or set of modules.\n    \"\"\"\n    module_ids = request.GET.get(\"modules\")\n    if module_ids is None or module_ids == '':\n        response = JsonResponse({\n            \"ok\": False,\n            \"error\": \"No module IDs provided.\"\n        }, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n    modules = module_ids.split(',')\n\n    date_filter = request.GET.get(\"date_filter\")\n    custom_timetable = get_custom_timetable(modules, date_filter)\n\n    if custom_timetable:\n        response_json = {\n            \"ok\": True,\n            \"timetable\": custom_timetable\n        }\n        return JsonResponse(response_json, custom_header_data=kwargs)\n    else:\n        response_json = {\n            \"ok\": False,\n            \"error\": \"One or more invalid Module IDs supplied.\"\n        }\n        response = JsonResponse(response_json, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    last_modified_redis_key='gencache'\n)\ndef get_departments_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns all departments at UCL\n    \"\"\"\n    departments = {\n        \"ok\": True,\n        \"departments\": get_departments()\n    }\n    return JsonResponse(departments, custom_header_data=kwargs)\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    last_modified_redis_key='gencache'\n)\ndef get_department_courses_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns all the courses in UCL with relevant ID\n    \"\"\"\n    try:\n        department_id = request.GET[\"department\"]\n    except KeyError:\n        response = JsonResponse({\n            \"ok\": False,\n            \"error\": \"No department ID provided.\"\n        }, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n    courses = {\"ok\": True, \"courses\": []}\n    for course in Course.objects.filter(owner=department_id,\n                                        setid=_SETID,\n                                        linkcode=\"YY\"):\n        courses[\"courses\"].append({\n            \"course_name\": course.name,\n            \"course_id\": course.courseid,\n            \"years\": course.numyears\n        })\n    return JsonResponse(courses, custom_header_data=kwargs)\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    last_modified_redis_key='gencache'\n)\ndef get_department_modules_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns all modules taught by a particular department.\n    \"\"\"\n    try:\n        department_id = request.GET[\"department\"]\n    except KeyError:\n        response = JsonResponse({\n            \"ok\": False,\n            \"error\": \"Supply a Department ID using the department parameter.\"\n        }, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n    modules = {\n        \"ok\": True,\n        \"modules\": get_departmental_modules(department_id)\n    }\n\n    return JsonResponse(modules, custom_header_data=kwargs)\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    last_modified_redis_key='timetable_gencache'\n)\ndef get_course_modules_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns all modules taught on a particular course.\n    \"\"\"\n    try:\n        course_id = request.GET[\"course\"]\n    except KeyError:\n        response = JsonResponse({\n            \"ok\": False,\n            \"error\": \"No course ID provided.\"\n        }, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n    if not validate_amp_query_params(request.query_params):\n        response = JsonResponse({\n            \"ok\": False,\n            \"error\": \"Given parameter is not of corrrect type\"\n        }, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n    if request.query_params.get('only_compulsory'):\n        try:\n            strtobool(request.query_params.get('only_compulsory'))\n        except ValueError:\n            response = JsonResponse({\n                \"ok\": False,\n                \"error\": \"Given parameter is not of correct type\"\n            }, custom_header_data=kwargs)\n            response.status_code = 400\n            return response\n\n    if request.query_params.get('only_available'):\n        try:\n            strtobool(request.query_params.get('only_available'))\n        except ValueError:\n            response = JsonResponse({\n                \"ok\": False,\n                \"error\": \"Given parameter is not of correct type\"\n            }, custom_header_data=kwargs)\n            response.status_code = 400\n            return response\n\n    if (request.query_params.get('only_available') and\n            request.query_params.get('only_compulsory')):\n        if (strtobool(request.query_params.get('only_available')) and\n                strtobool(request.query_params.get('only_compulsory'))):\n            response = JsonResponse({\n                \"ok\": False,\n                \"error\": \"only_available and only_compulsory\"\n                         \" cannot both be true\"\n            }, custom_header_data=kwargs)\n            response.status_code = 400\n            return response\n\n    modules = {\n        \"ok\": True,\n        \"modules\": get_course_modules(course_id, request.query_params)\n    }\n\n    return JsonResponse(modules, custom_header_data=kwargs)\n", "path": "backend/uclapi/timetable/views.py"}], "after_files": [{"content": "from distutils.util import strtobool\nfrom django.conf import settings\n\n\nfrom rest_framework.decorators import api_view\n\nfrom common.helpers import PrettyJsonResponse as JsonResponse\n\nfrom .models import Course\n\nfrom .app_helpers import (\n    get_custom_timetable,\n    get_departmental_modules,\n    get_departments,\n    get_student_timetable,\n    get_course_modules,\n    validate_amp_query_params\n)\n\nfrom common.decorators import uclapi_protected_endpoint\n\n_SETID = settings.ROOMBOOKINGS_SETID\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    personal_data=True,\n    required_scopes=['timetable'],\n    last_modified_redis_key='gencache'\n)\ndef get_personal_timetable_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns a personal timetable of a user. Requires OAuth permissions.\n    \"\"\"\n    token = kwargs['token']\n    user = token.user\n    date_filter = request.GET.get(\"date\")\n    timetable = get_student_timetable(user.employee_id, date_filter)\n\n    response = {\n        \"ok\": True,\n        \"timetable\": timetable\n    }\n    return JsonResponse(response, custom_header_data=kwargs)\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    last_modified_redis_key='gencache'\n)\ndef get_modules_timetable_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns a timetabe for a module or set of modules.\n    \"\"\"\n    module_ids = request.GET.get(\"modules\")\n    if module_ids is None or module_ids == '':\n        response = JsonResponse({\n            \"ok\": False,\n            \"error\": \"No module IDs provided.\"\n        }, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n    modules = module_ids.split(',')\n\n    date_filter = request.GET.get(\"date\")\n    custom_timetable = get_custom_timetable(modules, date_filter)\n\n    if custom_timetable:\n        response_json = {\n            \"ok\": True,\n            \"timetable\": custom_timetable\n        }\n        return JsonResponse(response_json, custom_header_data=kwargs)\n    else:\n        response_json = {\n            \"ok\": False,\n            \"error\": \"One or more invalid Module IDs supplied.\"\n        }\n        response = JsonResponse(response_json, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    last_modified_redis_key='gencache'\n)\ndef get_departments_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns all departments at UCL\n    \"\"\"\n    departments = {\n        \"ok\": True,\n        \"departments\": get_departments()\n    }\n    return JsonResponse(departments, custom_header_data=kwargs)\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    last_modified_redis_key='gencache'\n)\ndef get_department_courses_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns all the courses in UCL with relevant ID\n    \"\"\"\n    try:\n        department_id = request.GET[\"department\"]\n    except KeyError:\n        response = JsonResponse({\n            \"ok\": False,\n            \"error\": \"No department ID provided.\"\n        }, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n    courses = {\"ok\": True, \"courses\": []}\n    for course in Course.objects.filter(owner=department_id,\n                                        setid=_SETID,\n                                        linkcode=\"YY\"):\n        courses[\"courses\"].append({\n            \"course_name\": course.name,\n            \"course_id\": course.courseid,\n            \"years\": course.numyears\n        })\n    return JsonResponse(courses, custom_header_data=kwargs)\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    last_modified_redis_key='gencache'\n)\ndef get_department_modules_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns all modules taught by a particular department.\n    \"\"\"\n    try:\n        department_id = request.GET[\"department\"]\n    except KeyError:\n        response = JsonResponse({\n            \"ok\": False,\n            \"error\": \"Supply a Department ID using the department parameter.\"\n        }, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n    modules = {\n        \"ok\": True,\n        \"modules\": get_departmental_modules(department_id)\n    }\n\n    return JsonResponse(modules, custom_header_data=kwargs)\n\n\n@api_view([\"GET\"])\n@uclapi_protected_endpoint(\n    last_modified_redis_key='timetable_gencache'\n)\ndef get_course_modules_endpoint(request, *args, **kwargs):\n    \"\"\"\n    Returns all modules taught on a particular course.\n    \"\"\"\n    try:\n        course_id = request.GET[\"course\"]\n    except KeyError:\n        response = JsonResponse({\n            \"ok\": False,\n            \"error\": \"No course ID provided.\"\n        }, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n    if not validate_amp_query_params(request.query_params):\n        response = JsonResponse({\n            \"ok\": False,\n            \"error\": \"Given parameter is not of corrrect type\"\n        }, custom_header_data=kwargs)\n        response.status_code = 400\n        return response\n\n    if request.query_params.get('only_compulsory'):\n        try:\n            strtobool(request.query_params.get('only_compulsory'))\n        except ValueError:\n            response = JsonResponse({\n                \"ok\": False,\n                \"error\": \"Given parameter is not of correct type\"\n            }, custom_header_data=kwargs)\n            response.status_code = 400\n            return response\n\n    if request.query_params.get('only_available'):\n        try:\n            strtobool(request.query_params.get('only_available'))\n        except ValueError:\n            response = JsonResponse({\n                \"ok\": False,\n                \"error\": \"Given parameter is not of correct type\"\n            }, custom_header_data=kwargs)\n            response.status_code = 400\n            return response\n\n    if (request.query_params.get('only_available') and\n            request.query_params.get('only_compulsory')):\n        if (strtobool(request.query_params.get('only_available')) and\n                strtobool(request.query_params.get('only_compulsory'))):\n            response = JsonResponse({\n                \"ok\": False,\n                \"error\": \"only_available and only_compulsory\"\n                         \" cannot both be true\"\n            }, custom_header_data=kwargs)\n            response.status_code = 400\n            return response\n\n    modules = {\n        \"ok\": True,\n        \"modules\": get_course_modules(course_id, request.query_params)\n    }\n\n    return JsonResponse(modules, custom_header_data=kwargs)\n", "path": "backend/uclapi/timetable/views.py"}]}