diff --git a/schedule/views.py b/schedule/views.py index 2676f643..58248aa0 100644 --- a/schedule/views.py +++ b/schedule/views.py @@ -319,7 +319,12 @@ def _api_occurrences(start, end, calendar_slug, timezone): def convert(ddatetime): if ddatetime: ddatetime = ddatetime.split(' ')[0] - return datetime.datetime.strptime(ddatetime, '%Y-%m-%d') + try: + return datetime.datetime.strptime(ddatetime, '%Y-%m-%d') + except ValueError: + # try a different date string format first before failing + return datetime.datetime.strptime(ddatetime, '%Y-%m-%dT%H:%M:%S') + else: def convert(ddatetime): return datetime.datetime.utcfromtimestamp(float(ddatetime)) diff --git a/tests/test_views.py b/tests/test_views.py index d94ee8ca..b696bf85 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -318,6 +318,57 @@ def test_cal_slug_filters_returned_events(self): self.assertIn(event1.title, [d['title'] for d in resp_list]) self.assertNotIn(event2.title, [d['title'] for d in resp_list]) + def test_occurrences_api_works_with_different_date_string_formats(self): + # create a calendar and event + calendar = Calendar.objects.create(name="MyCal", slug='MyCalSlug') + event = Event.objects.create( + title='Recent Event', + start=datetime.datetime(2008, 1, 5, 8, 0, tzinfo=pytz.utc), + end=datetime.datetime(2008, 1, 5, 9, 0, tzinfo=pytz.utc), + end_recurring_period=datetime.datetime(2008, 5, 5, 0, 0, tzinfo=pytz.utc), + calendar=calendar, + ) + # test works with date string time format '%Y-%m-%d' + response = self.client.get(reverse('api_occurrences'), + {'start': '2008-01-05', + 'end': '2008-02-05', + 'calendar_slug': event.calendar.slug + }) + self.assertEqual(response.status_code, 200) + resp_list = json.loads(response.content.decode('utf-8')) + self.assertIn(event.title, [d['title'] for d in resp_list]) + # test works with date string time format '%Y-%m-%dT%H:%M:%S' + response = self.client.get(reverse("api_occurrences"), + {'start': '2008-01-05T00:00:00', + 'end': '2008-02-05T00:00:00', + 'calendar_slug': event.calendar.slug + }) + self.assertEqual(response.status_code, 200) + resp_list = json.loads(response.content.decode('utf-8')) + self.assertIn(event.title, [d['title'] for d in resp_list]) + + def test_occurrences_api_fails_with_incorrect_date_string_formats(self): + # create a calendar and event + calendar = Calendar.objects.create(name="MyCal", slug='MyCalSlug') + event = Event.objects.create( + title='Recent Event', + start=datetime.datetime(2008, 1, 5, 8, 0, tzinfo=pytz.utc), + end=datetime.datetime(2008, 1, 5, 9, 0, tzinfo=pytz.utc), + end_recurring_period=datetime.datetime(2008, 5, 5, 0, 0, tzinfo=pytz.utc), + calendar=calendar, + ) + + # test fails with date string time format not '%Y-%m-%d' or '%Y-%m-%dT%H:%M:%S' + response = self.client.get(reverse("api_occurrences"), + {'start': '2008-01-05T00:00', + 'end': '2008-02-05T00:00', + 'calendar_slug': event.calendar.slug + }) + self.assertEqual(response.status_code, 400) + resp = response.content.decode('utf-8') + expected_error = "does not match format '%Y-%m-%dT%H:%M:%S'" + self.assertIn(expected_error, resp) + def test_check_next_url_valid_case(self): expected = '/calendar/1' res = check_next_url('/calendar/1')