54

I have the next code:

users_table = Table(users_table_name, connection=Core.aws_dynamodb_connection)
users_table.put_item(data={
  "login": login,
  "password": hashlib.sha256(password.encode("utf-8")).hexdigest(),
  "profile": profile,
  "registration_date": datetime.now() # PROBLEM IS HERE
})

But when I run it, it fails with error:

TypeError: Unsupported type "< type 'datetime.datetime' >" for value "2015-01-12 05:02:57.053131"

I've tried a lot of ways, but it seems that it isn't possible to save datetime to DynamoDB. Btw it works fine in MongoDB.

Is there any solution?

Alexander Perechnev
  • 2,797
  • 3
  • 21
  • 35

9 Answers9

39

Okay, I see that DynamoDB does not support any date types. So the only solution is to use unix-like time as integer, or save date as string.

enter image description here

Alexander Perechnev
  • 2,797
  • 3
  • 21
  • 35
  • 1
    haha, so the problem really is **datetime** not supported :) and yes I think converting them to String is the way to go – Anzel Jan 12 '15 at 02:33
  • 3
    and you should accept your own answer so others will know why & what solutions they have in the same situation. – Anzel Jan 12 '15 at 02:35
  • @Alex Krzyżanowski I agree with Anzel. You should accept your answer as the correct answer. It is misleading to see the other answer marked as correct. – ishanbakshi Feb 09 '16 at 06:09
  • String and Number data types can be used. String when storing ISO8601 format, and Number when storing Epoch time. More info here: https://www.abhayachauhan.com/2017/12/how-to-store-dates-or-timestamps-in-dynamodb/ – Abhaya Chauhan Dec 13 '17 at 12:41
19

According to alejandro-franco response .isoformat() make the trick.

Just tested and this a working example:

CustomerPreferenceTable.put_item(
    Item={
        "id": str(uuid4()),
        "validAfter": datetime.utcnow().isoformat(),
        "validBefore": (datetime.utcnow() + timedelta(days=365)).isoformat(),
        "tags": ["potato", "eggplant"]
    }
)
user1855042
  • 621
  • 6
  • 5
  • 2
    Just be aware that datetime.utcnow() does not return a date with timezone information. So while parsing back, you should be knowing that stored information is UTC. Rather than that I would use datetime.utcnow().replace(tzinfo=timezone.utc).isoformat(), this way the generated information would be easily parsed with datetime.fromisoformat(). – ᐅdevrimbaris May 07 '20 at 10:34
  • Or better still, use datetime.now(tz=timezone.utc) as preferred in the Python documentation. – memento_mori_naps Dec 13 '22 at 05:24
14

According to the documentation: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/JavaSDKHighLevel.html

Date S (string type). The Date values are stored as ISO-8601 formatted strings.

Fred Campos
  • 1,457
  • 1
  • 19
  • 22
8

old post but maybe still interesting ..

What you can do and how it worked for me:

import datetime
from datetime import datetime

...

now = datetime.now()
x = now.strftime("%m/%d/%Y, %H:%M:%S")

 table.put_item(
           Item={
               'Index': Index,
           
               'Stamp': x,
               
            }
        )

And with adaption to the code above:

import datetime
from datetime import datetime

...

now = datetime.now()
x = now.strftime("%m/%d/%Y, %H:%M:%S")

users_table = Table(users_table_name, connection=Core.aws_dynamodb_connection)
users_table.put_item(data={
  "login": login,
  "password": hashlib.sha256(password.encode("utf-8")).hexdigest(),
  "profile": profile,
  "registration_date": x, 
})   

My Output

You can see the format in the DB

machin
  • 440
  • 8
  • 21
dvoelker
  • 101
  • 2
  • 4
4

Reading the documentation lately, I found the right link to the documentation here. The recommended way to store date and time data in DynamoDB is using ISO 8601 strings. so the data type is just string.

Ramy M. Mousa
  • 5,727
  • 3
  • 34
  • 45
alejo4373
  • 115
  • 7
3

I'm not sure why datetime isn't supported in DynamoDB, or in fact I have no experience in it neither.

But if you're so insisted in not converting the datetime to string like people suggested, you can convert the datetime to timestamp, and so you can compare with it.

updated

And you may want to read this SO Question, seemed like numeric comparison is the preferred way.

Community
  • 1
  • 1
Anzel
  • 19,825
  • 5
  • 51
  • 52
  • Thank you for response. I am not sure if it is possible in case of storing date as string to query objects by range. So timestamp is the only solution. Thank's to Amazon ahaha :). – Alexander Perechnev Jan 12 '15 at 02:35
  • JSON doesn't specify how a datetime should be represented. DynamoDB has kicked off with support JSON field types. – Carl Feb 24 '16 at 16:31
  • Another good reason to store datetimes as a normal epoch-based timestamps is that this is what Time To Live is based on. http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/time-to-live-ttl-how-to.html – Michael Scheper Jun 14 '17 at 22:25
2

If you want to use date to find users, you can simply invoke date() function. Like this:

...
users_table = Table(users_table_name, connection=Core.aws_dynamodb_connection)
current = datetime.now()
users_table.put_item(data={
  "login": login,
  "password": hashlib.sha256(password.encode("utf-8")).hexdigest(),
  "profile": profile,
  # here use a different name for the entry
  "registration_time": current
  "registration_date": current.date()
})
...
Stephen Lin
  • 4,852
  • 1
  • 13
  • 26
  • No, it doesn't decide the problem. It throws error because it won't accept standard python date objects. I've edited my question to make it more clear. – Alexander Perechnev Jan 12 '15 at 02:25
1

These are all the supported types for attribute values in DynamoDB as listed in their AWS Docs.

B A Binary data type.

Type: Blob

Required: No

BOOL A Boolean data type.

Type: Boolean

Required: No

BS A Binary Set data type.

Type: array of Blobs

Required: No

L A List of attribute values.

Type: array of AttributeValue objects

Required: No

M A Map of attribute values.

Type: String to AttributeValue object map

Required: No

N A Number data type.

Type: String

Required: No

NS A Number Set data type.

Type: array of Strings

Required: No

NULL A Null data type.

Type: Boolean

Required: No

S A String data type.

Type: String

Required: No

SS A String Set data type.

Type: array of Strings

Required: No

disco crazy
  • 31,313
  • 12
  • 80
  • 83
1

with DDB2, seems like Instant is now supported.

https://github.com/aws/aws-sdk-java-v2/tree/master/services-custom/dynamodb-enhanced#changing-update-behavior-of-attributes

Ruelos Joel
  • 2,209
  • 3
  • 19
  • 33