Repository: Azure/msrest-for-python

Issue:
Parsing RFC date assumes current local is English
Example, trying to parse `Fri, 28 Feb 2020 19:04:06 GMT` with a spanish locale will fail, since "Fri" or "Feb" is not spanish.
This is because this parser uses `strptime` which is local dependent. Python doesn't support configuration for locale.

The only reliable way would be to stop using "strptime", since other solution like [this ](https://stackoverflow.com/a/24070673/4074838)relies on a thread lock and I don't like that.

Discussion:
lmazuel: Without the PR, trying to deserialize in a french VM:
```python
>>> from msrest.serialization import Deserializer
>>> Deserializer.deserialize_rfc("Mon, 20 Nov 1995 19:12:08 -0500")
Traceback (most recent call last):
  File "/home/lmazuel/rfctest/lib/python3.6/site-packages/msrest/serialization.py", line 1818, in deserialize_rfc
    attr, "%a, %d %b %Y %H:%M:%S %Z")
  File "/usr/lib/python3.6/_strptime.py", line 565, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib/python3.6/_strptime.py", line 362, in _strptime
    (data_string, format))
ValueError: time data 'Mon, 20 Nov 1995 19:12:08 -0500' does not match format '%a, %d %b %Y %H:%M:%S %Z'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/lmazuel/rfctest/lib/python3.6/site-packages/msrest/serialization.py", line 1823, in deserialize_rfc
    raise_with_traceback(DeserializationError, msg, err)
  File "/home/lmazuel/rfctest/lib/python3.6/site-packages/msrest/exceptions.py", line 51, in raise_with_traceback
    raise error.with_traceback(exc_traceback)
  File "/home/lmazuel/rfctest/lib/python3.6/site-packages/msrest/serialization.py", line 1818, in deserialize_rfc
    attr, "%a, %d %b %Y %H:%M:%S %Z")
  File "/usr/lib/python3.6/_strptime.py", line 565, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib/python3.6/_strptime.py", line 362, in _strptime
    (data_string, format))
msrest.exceptions.DeserializationError: Cannot deserialize to rfc datetime object., ValueError: time data 'Mon, 20 Nov 1995 19:12:08 -0500' does not match format '%a, %d %b %Y %H:%M:%S %Z'
```

With the PR:
```python
>>> from msrest.serialization import Deserializer
>>> Deserializer.deserialize_rfc("Mon, 20 Nov 1995 19:12:08 -0500")
datetime.datetime(1995, 11, 20, 19, 12, 8, tzinfo=<FixedOffset -5.0>)
```

Patch:
diff --git a/msrest/serialization.py b/msrest/serialization.py
index 59187e1..0e65d8e 100644
--- a/msrest/serialization.py
+++ b/msrest/serialization.py
@@ -28,6 +28,7 @@ from base64 import b64decode, b64encode
 import calendar
 import datetime
 import decimal
+import email
 from enum import Enum
 import json
 import logging
@@ -78,6 +79,26 @@ class UTC(datetime.tzinfo):
         """No daylight saving for UTC."""
         return datetime.timedelta(hours=1)
 
+class _FixedOffset(datetime.tzinfo):
+    """Fixed offset in minutes east from UTC.
+    Copy/pasted from Python doc
+    :param int offset: offset in minutes
+    """
+
+    def __init__(self, offset):
+        self.__offset = datetime.timedelta(minutes=offset)
+
+    def utcoffset(self, dt):
+        return self.__offset
+
+    def tzname(self, dt):
+        return str(self.__offset.total_seconds()/3600)
+
+    def __repr__(self):
+        return "<FixedOffset {}>".format(self.tzname(None))
+
+    def dst(self, dt):
+        return datetime.timedelta(0)
 
 try:
     from datetime import timezone
@@ -1814,10 +1835,13 @@ class Deserializer(object):
         if isinstance(attr, ET.Element):
             attr = attr.text
         try:
-            date_obj = datetime.datetime.strptime(
-                attr, "%a, %d %b %Y %H:%M:%S %Z")
+            parsed_date = email.utils.parsedate_tz(attr)
+            date_obj = datetime.datetime(
+                *parsed_date[:6],
+                tzinfo=_FixedOffset((parsed_date[9] or 0)/60)
+            )
             if not date_obj.tzinfo:
-                date_obj = date_obj.replace(tzinfo=TZ_UTC)
+                date_obj = date_obj.astimezone(tz=TZ_UTC)
         except ValueError as err:
             msg = "Cannot deserialize to rfc datetime object."
             raise_with_traceback(DeserializationError, msg, err)


Test patch:
diff --git a/tests/test_serialization.py b/tests/test_serialization.py
index 12a0042..fffd8a9 100644
--- a/tests/test_serialization.py
+++ b/tests/test_serialization.py
@@ -1974,6 +1974,55 @@ class TestRuntimeDeserialized(unittest.TestCase):
         self.assertEqual(utc.tm_sec, 52)
         self.assertEqual(a.microsecond, 780000)
 
+    def test_deserialize_datetime_rfc(self):
+
+        a = Deserializer.deserialize_rfc("Mon, 20 Nov 1995 19:12:08 -0500")
+        utc = a.utctimetuple()
+
+        # UTC: 21 Nov, 00:12:08
+        self.assertEqual(utc.tm_year, 1995)
+        self.assertEqual(utc.tm_mon, 11)
+        self.assertEqual(utc.tm_mday, 21)
+        self.assertEqual(utc.tm_hour, 0)
+        self.assertEqual(utc.tm_min, 12)
+        self.assertEqual(utc.tm_sec, 8)
+        self.assertEqual(a.microsecond, 0)
+
+        a = Deserializer.deserialize_rfc("Mon, 20 Nov 1995 19:12:08 CDT")
+        utc = a.utctimetuple()
+
+        # UTC: 21 Nov, 00:12:08
+        self.assertEqual(utc.tm_year, 1995)
+        self.assertEqual(utc.tm_mon, 11)
+        self.assertEqual(utc.tm_mday, 21)
+        self.assertEqual(utc.tm_hour, 0)
+        self.assertEqual(utc.tm_min, 12)
+        self.assertEqual(utc.tm_sec, 8)
+        self.assertEqual(a.microsecond, 0)
+
+        a = Deserializer.deserialize_rfc("Mon, 20 Nov 1995 19:12:08")
+        utc = a.utctimetuple()
+
+        # UTC: No info is considered UTC
+        self.assertEqual(utc.tm_year, 1995)
+        self.assertEqual(utc.tm_mon, 11)
+        self.assertEqual(utc.tm_mday, 20)
+        self.assertEqual(utc.tm_hour, 19)
+        self.assertEqual(utc.tm_min, 12)
+        self.assertEqual(utc.tm_sec, 8)
+        self.assertEqual(a.microsecond, 0)
+
+        a = Deserializer.deserialize_rfc("Mon, 20 Nov 1995 19:12:08 GMT")
+        utc = a.utctimetuple()
+
+        self.assertEqual(utc.tm_year, 1995)
+        self.assertEqual(utc.tm_mon, 11)
+        self.assertEqual(utc.tm_mday, 20)
+        self.assertEqual(utc.tm_hour, 19)
+        self.assertEqual(utc.tm_min, 12)
+        self.assertEqual(utc.tm_sec, 8)
+        self.assertEqual(a.microsecond, 0)
+
     def test_polymorphic_deserialization(self):
 
         class Zoo(Model):