diff --git a/falcon/request.py b/falcon/request.py index 8b8f972a7..40ed7e49f 100644 --- a/falcon/request.py +++ b/falcon/request.py @@ -1181,17 +1181,17 @@ def get_param_as_list(self, name, raise errors.HTTPMissingParam(name) - def get_param_as_date(self, name, format_string='%Y-%m-%d', - required=False, store=None): - """Return the value of a query string parameter as a date. + def get_param_as_datetime(self, name, format_string='%Y-%m-%dT%H:%M:%SZ', + required=False, store=None): + """Return the value of a query string parameter as a datetime. Args: name (str): Parameter name, case-sensitive (e.g., 'ids'). Keyword Args: format_string (str): String used to parse the param value - into a date. Any format recognized by strptime() is - supported (default ``"%Y-%m-%d"``). + into a datetime. Any format recognized by strptime() is + supported (default ``'%Y-%m-%dT%H:%M:%SZ'``). required (bool): Set to ``True`` to raise ``HTTPBadRequest`` instead of returning ``None`` when the parameter is not found (default ``False``). @@ -1199,8 +1199,8 @@ def get_param_as_date(self, name, format_string='%Y-%m-%d', the value of the param, but only if the param is found (default ``None``). Returns: - datetime.date: The value of the param if it is found and can be - converted to a ``date`` according to the supplied format + datetime.datetime: The value of the param if it is found and can be + converted to a ``datetime`` according to the supplied format string. If the param is not found, returns ``None`` unless required is ``True``. @@ -1216,11 +1216,51 @@ def get_param_as_date(self, name, format_string='%Y-%m-%d', return None try: - date = strptime(param_value, format_string).date() + date_time = strptime(param_value, format_string) except ValueError: msg = 'The date value does not match the required format.' raise errors.HTTPInvalidParam(msg, name) + if store is not None: + store[name] = date_time + + return date_time + + def get_param_as_date(self, name, format_string='%Y-%m-%d', + required=False, store=None): + """Return the value of a query string parameter as a date. + + Args: + name (str): Parameter name, case-sensitive (e.g., 'ids'). + + Keyword Args: + format_string (str): String used to parse the param value + into a date. Any format recognized by strptime() is + supported (default ``"%Y-%m-%d"``). + required (bool): Set to ``True`` to raise + ``HTTPBadRequest`` instead of returning ``None`` when the + parameter is not found (default ``False``). + store (dict): A ``dict``-like object in which to place + the value of the param, but only if the param is found (default + ``None``). + Returns: + datetime.date: The value of the param if it is found and can be + converted to a ``date`` according to the supplied format + string. If the param is not found, returns ``None`` unless + required is ``True``. + + Raises: + HTTPBadRequest: A required param is missing from the request. + HTTPInvalidParam: A transform function raised an instance of + ``ValueError``. + """ + + date_time = self.get_param_as_datetime(name, format_string, required) + if date_time: + date = date_time.date() + else: + return None + if store is not None: store[name] = date diff --git a/tests/test_query_params.py b/tests/test_query_params.py index 4be4674b3..e90567d4b 100644 --- a/tests/test_query_params.py +++ b/tests/test_query_params.py @@ -1,4 +1,5 @@ -from datetime import date +from datetime import date, datetime + try: import ujson as json except ImportError: @@ -578,6 +579,52 @@ def test_get_date_invalid(self, simulate_request, client, resource): with pytest.raises(HTTPInvalidParam): req.get_param_as_date('thedate', format_string=format_string) + def test_get_datetime_valid(self, simulate_request, client, resource): + client.app.add_route('/', resource) + date_value = '2015-04-20T10:10:10Z' + query_string = 'thedate={0}'.format(date_value) + simulate_request(client=client, path='/', query_string=query_string) + req = resource.captured_req + assert req.get_param_as_datetime('thedate') == datetime(2015, 4, 20, 10, 10, 10) + + def test_get_datetime_missing_param(self, simulate_request, client, resource): + client.app.add_route('/', resource) + query_string = 'notthedate=2015-04-20T10:10:10Z' + simulate_request(client=client, path='/', query_string=query_string) + req = resource.captured_req + assert req.get_param_as_datetime('thedate') is None + + def test_get_datetime_valid_with_format(self, simulate_request, client, resource): + client.app.add_route('/', resource) + date_value = '20150420 10:10:10' + query_string = 'thedate={0}'.format(date_value) + format_string = '%Y%m%d %H:%M:%S' + simulate_request(client=client, path='/', query_string=query_string) + req = resource.captured_req + assert req.get_param_as_datetime( + 'thedate', format_string=format_string) == datetime(2015, 4, 20, 10, 10, 10) + + def test_get_datetime_store(self, simulate_request, client, resource): + client.app.add_route('/', resource) + datetime_value = '2015-04-20T10:10:10Z' + query_string = 'thedate={0}'.format(datetime_value) + simulate_request(client=client, path='/', query_string=query_string) + req = resource.captured_req + store = {} + req.get_param_as_datetime('thedate', store=store) + assert len(store) != 0 + assert store.get('thedate') == datetime(2015, 4, 20, 10, 10, 10) + + def test_get_datetime_invalid(self, simulate_request, client, resource): + client.app.add_route('/', resource) + date_value = 'notarealvalue' + query_string = 'thedate={0}'.format(date_value) + format_string = '%Y%m%dT%H:%M:%S' + simulate_request(client=client, path='/', query_string=query_string) + req = resource.captured_req + with pytest.raises(HTTPInvalidParam): + req.get_param_as_datetime('thedate', format_string=format_string) + def test_get_dict_valid(self, simulate_request, client, resource): client.app.add_route('/', resource) payload_dict = {'foo': 'bar'}