Repository: getmoto/moto

Issue:
Cloudwatch issue with Timestamp and Label
Hello! I testing moto from ba2ea8e1b32348346f382a19ee6d0e99a3c63fa3 .  I found what I believe are two minor issues that I'd like to help fix.

I'd like to submit the PR to fix these issues once confirmed.

1.  https://github.com/spulec/moto/blob/81f3cbb54880bdf68fd6f52b9aa30ea25a4b7bd9/moto/cloudwatch/responses.py#L275 includes whitespace in the response.  This is causing Label for metric name to have extra spaces like such: `' CPUUtilization '` in `get_metric_statistics`.

2. When using `put_metric_data` and including `Timestamp` argument; the data is converted from `datetime` to `str` somewhere in the model.  This is causing an exception when making a subsequent call to `get_metric_statistics`.

    ```
    "moto/cloudwatch/models.py", line 238, in get_metric_statistics
    md.namespace == namespace and md.name == metric_name and start_time <= md.timestamp <= end_time]
    TypeError: can't compare datetime.datetime to unicode
     ```

Patch for item 2 reproduction

```
diff --git a/tests/test_cloudwatch/test_cloudwatch_boto3.py b/tests/test_cloudwatch/test_cloudwatch_boto3.py
index 5fbf757..58ccf46 100644
--- a/tests/test_cloudwatch/test_cloudwatch_boto3.py
+++ b/tests/test_cloudwatch/test_cloudwatch_boto3.py
@@ -173,6 +173,7 @@ def test_get_metric_statistics():
             dict(
                 MetricName='metric',
                 Value=1.5,
+                Timestamp=utc_now
             )
         ]
     )
@@ -180,7 +181,7 @@ def test_get_metric_statistics():
     stats = conn.get_metric_statistics(
         Namespace='tester',
         MetricName='metric',
-        StartTime=utc_now,
+        StartTime=utc_now - timedelta(seconds=60),
         EndTime=utc_now + timedelta(seconds=60),
         Period=60,
         Statistics=['SampleCount', 'Sum']
```


Discussion:

Resolving patch:
diff --git a/moto/cloudwatch/models.py b/moto/cloudwatch/models.py
--- a/moto/cloudwatch/models.py
+++ b/moto/cloudwatch/models.py
@@ -229,8 +229,13 @@ def delete_alarms(self, alarm_names):
 
     def put_metric_data(self, namespace, metric_data):
         for metric_member in metric_data:
+            # Preserve "datetime" for get_metric_statistics comparisons
+            timestamp = metric_member.get('Timestamp')
+            if timestamp is not None and type(timestamp) != datetime:
+                timestamp = datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%fZ')
+                timestamp = timestamp.replace(tzinfo=tzutc())
             self.metric_data.append(MetricDatum(
-                namespace, metric_member['MetricName'], float(metric_member['Value']), metric_member.get('Dimensions.member', _EMPTY_LIST), metric_member.get('Timestamp')))
+                namespace, metric_member['MetricName'], float(metric_member['Value']), metric_member.get('Dimensions.member', _EMPTY_LIST), timestamp))
 
     def get_metric_statistics(self, namespace, metric_name, start_time, end_time, period, stats):
         period_delta = timedelta(seconds=period)
diff --git a/moto/cloudwatch/responses.py b/moto/cloudwatch/responses.py
--- a/moto/cloudwatch/responses.py
+++ b/moto/cloudwatch/responses.py
@@ -272,7 +272,7 @@ def set_alarm_state(self):
    </ResponseMetadata>
 
   <GetMetricStatisticsResult>
-      <Label> {{ label }} </Label>
+      <Label>{{ label }}</Label>
       <Datapoints>
         {% for datapoint in datapoints %}
             <Datapoint>


Test patch:
diff --git a/tests/test_cloudwatch/test_cloudwatch_boto3.py b/tests/test_cloudwatch/test_cloudwatch_boto3.py
--- a/tests/test_cloudwatch/test_cloudwatch_boto3.py
+++ b/tests/test_cloudwatch/test_cloudwatch_boto3.py
@@ -173,6 +173,7 @@ def test_get_metric_statistics():
             dict(
                 MetricName='metric',
                 Value=1.5,
+                Timestamp=utc_now
             )
         ]
     )
@@ -180,7 +181,7 @@ def test_get_metric_statistics():
     stats = conn.get_metric_statistics(
         Namespace='tester',
         MetricName='metric',
-        StartTime=utc_now,
+        StartTime=utc_now - timedelta(seconds=60),
         EndTime=utc_now + timedelta(seconds=60),
         Period=60,
         Statistics=['SampleCount', 'Sum']