Repository: falconry/falcon

Issue:
Support obsolete HTTP date formats
In looking at [RFC 7231](http://tools.ietf.org/html/rfc7231#section-7.1.1.1), Falcon date parsing is actually restricted to IMF-fixdate and does not support the other two obsolete formats. Should we support those formats? Doing so may have minor performance implications for little benefit.

Otherwise, we should update the docstrings and such to reference IMF-fixdate instead of HTTP-Date.



Discussion:
I forgot to say so before I started working on this but I will do this. About to submit a PR for it.

Let's wait just a sec. There's a PR about to merge that may give you conflicts.

See also: #482


Resolving patch:
diff --git a/falcon/request.py b/falcon/request.py
--- a/falcon/request.py
+++ b/falcon/request.py
@@ -617,12 +617,13 @@ def get_header_as_datetime(self, header, required=False):
 
         try:
             http_date = self.get_header(header, required=required)
-            return util.http_date_to_dt(http_date)
+            return util.http_date_to_dt(http_date, obs_date=True)
         except TypeError:
             # When the header does not exist and isn't required
             return None
         except ValueError:
-            msg = ('It must be formatted according to RFC 1123.')
+            msg = ('It must be formatted according to RFC 7231, '
+                   'Section 7.1.1.1')
             raise HTTPInvalidHeader(msg, header)
 
     def get_param(self, name, required=False, store=None, default=None):
diff --git a/falcon/util/misc.py b/falcon/util/misc.py
--- a/falcon/util/misc.py
+++ b/falcon/util/misc.py
@@ -88,19 +88,41 @@ def dt_to_http(dt):
     return dt.strftime('%a, %d %b %Y %H:%M:%S GMT')
 
 
-def http_date_to_dt(http_date):
+def http_date_to_dt(http_date, obs_date=False):
     """Converts an HTTP date string to a datetime instance.
 
     Args:
         http_date (str): An RFC 1123 date string, e.g.:
             "Tue, 15 Nov 1994 12:45:26 GMT".
+        obs_date (bool): Support obs-date formats according to RFC 7231, e.g.:
+            "Sunday, 06-Nov-94 08:49:37 GMT"
+            "Sun Nov  6 08:49:37 1994".
 
     Returns:
         datetime: A UTC datetime instance corresponding to the given
             HTTP date.
+
+    Raises:
+        ValueError: http_date doesn't match any of the available time formats
     """
 
-    return strptime(http_date, '%a, %d %b %Y %H:%M:%S %Z')
+    time_formats = ['%a, %d %b %Y %H:%M:%S %Z']
+
+    if obs_date:
+        time_formats.extend([
+            '%A, %d-%b-%y %H:%M:%S %Z',
+            '%a %b %d %H:%M:%S %Y',
+        ])
+
+    # Loop through the formats and return the first that matches
+    for time_format in time_formats:
+        try:
+            return strptime(http_date, time_format)
+        except ValueError:
+            continue
+
+    # Did not match any formats
+    raise ValueError('time data %r does not match known formats' % http_date)
 
 
 def to_query_str(params):


Test patch:
diff --git a/tests/test_req_vars.py b/tests/test_req_vars.py
--- a/tests/test_req_vars.py
+++ b/tests/test_req_vars.py
@@ -527,7 +527,7 @@ def test_date_invalid(self, header, attr):
         headers = {header: 'Thu, 04 Apr 2013'}
         expected_desc = ('The value provided for the {0} '
                          'header is invalid. It must be formatted '
-                         'according to RFC 1123.')
+                         'according to RFC 7231, Section 7.1.1.1')
 
         self._test_error_details(headers, attr,
                                  falcon.HTTPInvalidHeader,
diff --git a/tests/test_utils.py b/tests/test_utils.py
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -70,6 +70,15 @@ def test_http_date_to_dt(self):
             falcon.http_date_to_dt('Thu, 04 Apr 2013 10:28:54 GMT'),
             datetime(2013, 4, 4, 10, 28, 54))
 
+        self.assertEqual(
+            falcon.http_date_to_dt('Sunday, 06-Nov-94 08:49:37 GMT',
+                                   obs_date=True),
+            datetime(1994, 11, 6, 8, 49, 37))
+
+        self.assertEqual(
+            falcon.http_date_to_dt('Sun Nov  6 08:49:37 1994', obs_date=True),
+            datetime(1994, 11, 6, 8, 49, 37))
+
     def test_pack_query_params_none(self):
         self.assertEqual(
             falcon.to_query_str({}),