Repository: getmoto/moto

Issue:
Several KMS operations are broken on Windows in 1.3.8
The change from https://github.com/spulec/moto/pull/2073 breaks several KMS operations on Windows because the `%s` format specifier is platform specific and not supported in python.

This can be easily fixed by changing the timestamp generation to use:
> `(datetime.utcnow() - datetime(1970, 1, 1)).total_seconds()`

An example stack trace of a test that throws is included below.

```
tests\test_kms.py:33: in _create_kms_key
    key = kms_client.create_key(Policy="Policy", KeyUsage='ENCRYPT_DECRYPT')
wenv\lib\site-packages\botocore\client.py:357: in _api_call
    return self._make_api_call(operation_name, kwargs)
wenv\lib\site-packages\botocore\client.py:648: in _make_api_call
    operation_model, request_dict, request_context)
wenv\lib\site-packages\botocore\client.py:667: in _make_request
    return self._endpoint.make_request(operation_model, request_dict)
wenv\lib\site-packages\botocore\endpoint.py:102: in make_request
    return self._send_request(request_dict, operation_model)
wenv\lib\site-packages\botocore\endpoint.py:137: in _send_request
    success_response, exception):
wenv\lib\site-packages\botocore\endpoint.py:231: in _needs_retry
    caught_exception=caught_exception, request_dict=request_dict)
wenv\lib\site-packages\botocore\hooks.py:356: in emit
    return self._emitter.emit(aliased_event_name, **kwargs)
wenv\lib\site-packages\botocore\hooks.py:228: in emit
    return self._emit(event_name, kwargs)
wenv\lib\site-packages\botocore\hooks.py:211: in _emit
    response = handler(**kwargs)
wenv\lib\site-packages\botocore\retryhandler.py:183: in __call__
    if self._checker(attempts, response, caught_exception):
wenv\lib\site-packages\botocore\retryhandler.py:251: in __call__
    caught_exception)
wenv\lib\site-packages\botocore\retryhandler.py:269: in _should_retry
    return self._checker(attempt_number, response, caught_exception)
wenv\lib\site-packages\botocore\retryhandler.py:317: in __call__
    caught_exception)
wenv\lib\site-packages\botocore\retryhandler.py:223: in __call__
    attempt_number, caught_exception)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <botocore.retryhandler.ExceptionRaiser object at 0x0000000011A51A58>
attempt_number = 1, caught_exception = ValueError('Invalid format string',)

    def _check_caught_exception(self, attempt_number, caught_exception):
        # This is implementation specific, but this class is useful by
        # coordinating with the MaxAttemptsDecorator.
        # The MaxAttemptsDecorator has a list of exceptions it should catch
        # and retry, but something needs to come along and actually raise the
        # caught_exception.  That's what this class is being used for.  If
        # the MaxAttemptsDecorator is not interested in retrying the exception
        # then this exception just propogates out past the retry code.
        print(dir(caught_exception))
>       raise caught_exception
E       ValueError: Invalid format string
```



Discussion:

Resolving patch:
diff --git a/moto/kms/models.py b/moto/kms/models.py
--- a/moto/kms/models.py
+++ b/moto/kms/models.py
@@ -3,7 +3,7 @@
 import os
 import boto.kms
 from moto.core import BaseBackend, BaseModel
-from moto.core.utils import iso_8601_datetime_without_milliseconds
+from moto.core.utils import iso_8601_datetime_without_milliseconds, unix_time
 from .utils import generate_key_id
 from collections import defaultdict
 from datetime import datetime, timedelta
@@ -37,7 +37,7 @@ def to_dict(self):
             "KeyMetadata": {
                 "AWSAccountId": self.account_id,
                 "Arn": self.arn,
-                "CreationDate": datetime.strftime(datetime.utcnow(), "%s"),
+                "CreationDate": "%d" % unix_time(),
                 "Description": self.description,
                 "Enabled": self.enabled,
                 "KeyId": self.id,


Test patch:
diff --git a/tests/test_kms/test_kms.py b/tests/test_kms/test_kms.py
--- a/tests/test_kms/test_kms.py
+++ b/tests/test_kms/test_kms.py
@@ -18,13 +18,14 @@
 @mock_kms_deprecated
 def test_create_key():
     conn = boto.kms.connect_to_region("us-west-2")
+    with freeze_time("2015-01-01 00:00:00"):
+        key = conn.create_key(policy="my policy",
+                            description="my key", key_usage='ENCRYPT_DECRYPT')
 
-    key = conn.create_key(policy="my policy",
-                          description="my key", key_usage='ENCRYPT_DECRYPT')
-
-    key['KeyMetadata']['Description'].should.equal("my key")
-    key['KeyMetadata']['KeyUsage'].should.equal("ENCRYPT_DECRYPT")
-    key['KeyMetadata']['Enabled'].should.equal(True)
+        key['KeyMetadata']['Description'].should.equal("my key")
+        key['KeyMetadata']['KeyUsage'].should.equal("ENCRYPT_DECRYPT")
+        key['KeyMetadata']['Enabled'].should.equal(True)
+        key['KeyMetadata']['CreationDate'].should.equal("1420070400")
 
 
 @mock_kms_deprecated
@@ -980,5 +981,3 @@ def test_put_key_policy_key_not_found():
             PolicyName='default',
             Policy='new policy'
         )
-
-