能否将日期时间保存到DynamoDB中?

54

我有以下代码:

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
})

但是当我运行它时,出现以下错误:

TypeError: 对于值"2015-01-12 05:02:57.053131"不支持类型"< type 'datetime.datetime' >"

我尝试了很多方法,但似乎无法将datetime保存到DynamoDB中。顺便说一句,在MongoDB中可以正常工作。

有什么解决办法吗?


14
为什么会有人踩我?我已经花了约3个小时寻找任何例子,阅读了很多文档,但没有看到任何关于我的问题的信息。 - Alexander Perechnev
2
也许将类型从datetime.datetime更改为字符串,然后将其存储到数据库中? - Stephen Lin
@m170897017,这不是一个解决方案,因为我需要按注册日期范围查找用户。 - Alexander Perechnev
9个回答

39

好的,我看到 DynamoDB 不支持任何日期类型。因此唯一的解决方案是使用类 Unix 时间作为整数,或将日期保存为字符串。

输入图像描述


1
哈哈,问题确实是datetime不支持 :) 是的,我认为将它们转换为字符串是正确的方法。 - Anzel
3
你应该接受自己的答案,这样其他人就会知道在相同的情况下为什么以及有哪些解决方案。 - Anzel
@Alex Krzyżanowski,我同意Anzel的观点。您应该将自己的回答作为正确答案接受。标记其他答案为正确答案是误导性的。 - ishanbakshi
可以使用字符串和数字数据类型。在存储ISO8601格式时使用字符串,在存储Epoch时间时使用数字。更多信息请参见:https://www.abhayachauhan.com/2017/12/how-to-store-dates-or-timestamps-in-dynamodb/ - Abhaya Chauhan

19

根据alejandro-franco的回答.isoformat()就能搞定。

刚刚测试了一下,这是一个可行的例子:

CustomerPreferenceTable.put_item(
    Item={
        "id": str(uuid4()),
        "validAfter": datetime.utcnow().isoformat(),
        "validBefore": (datetime.utcnow() + timedelta(days=365)).isoformat(),
        "tags": ["potato", "eggplant"]
    }
)

2
请注意,datetime.utcnow()不会返回带有时区信息的日期。因此,在解析回来时,您应该知道存储的信息是UTC。与其如此,我会使用datetime.utcnow().replace(tzinfo=timezone.utc).isoformat(),这样生成的信息将很容易地通过datetime.fromisoformat()进行解析。 - ᐅdevrimbaris
或者更好的方法是,按照Python文档中的建议使用datetime.now(tz=timezone.utc)。 - memento_mori_naps

14

1
你在哪里看到它? - Dejell
1
你能更新你的答案吗?如果链接不存在:请写下您不再看到它。 - Dejell
1
@FredCampos 链接又存在了!你应该编辑你的回答 :) - fIwJlxSzApHEZIl
这仅适用于Java。不适用于Python。 - Tim Ludwinski

8

虽然这篇文章有点旧,但仍然很有意思。

以下是你可以做的事情以及它如何对我起作用:

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,
               
            }
        )

并根据上面的代码进行适应:

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, 
})   

我的输出

您可以在数据库中看到格式


4

最近阅读文档时,我找到了正确的文档链接这里。在DynamoDB中存储日期和时间数据的推荐方式是使用ISO 8601字符串,因此数据类型只是字符串。


3
我不确定为什么DynamoDB不支持datetime,实际上我也没有相关经验。
但是,如果你坚持不像其他人建议的将datetime转换为字符串,你可以将datetime转换为timestamp,然后进行比较。
更新:
你可能想阅读这个SO问题,似乎数字比较是首选方法。

谢谢您的回复。如果将日期存储为字符串,是否可以通过范围查询对象是不确定的。因此,时间戳是唯一的解决方案。感谢亚马逊哈哈:)。 - Alexander Perechnev
JSON不指定日期时间的表示方式。 DynamoDB已经启动,支持JSON字段类型。 - Carl
将日期时间存储为普通的基于时代的时间戳的另一个好处是,这是过期时间(TTL)所基于的内容。http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/time-to-live-ttl-how-to.html - Michael Scheper

2

如果您想使用日期查找用户,可以简单地调用date()函数。就像这样:

...
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()
})
...

不,这并没有解决问题。它会抛出错误,因为它不接受标准的Python日期对象。我已经编辑了我的问题,使其更清晰明了。 - Alexander Perechnev

1
这些都是DynamoDB支持的属性值类型,详见AWS文档

B 二进制数据类型。

类型:Blob

必填:否

BOOL 布尔数据类型。

类型:Boolean

必填:否

BS 二进制集合数据类型。

类型:Blob 数组

必填:否

L 属性值列表。

类型:AttributeValue 对象数组

必填:否

M 属性值映射。

类型:字符串到 AttributeValue 对象的映射

必填:否

N 数字数据类型。

类型:字符串

必填:否

NS 数字集合数据类型。

类型:字符串数组

必填:否

NULL 空数据类型。

类型:Boolean

必填:否

S 字符串数据类型。

类型:字符串

必填:否

SS 字符串集合数据类型。

类型:字符串数组

必填:否



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接