在DynamoDB中,应该使用什么数据类型来表示时间戳?

151

我是DynamoDB的新手,希望创建一个表,使用DeviceID作为哈希键,Timestamp作为范围键并加入一些数据。

{ DeviceID: 123, Timestamp: "2016-11-11T17:21:07.5272333Z", X: 12, Y: 35 }

在SQL中,我们可以使用datetime类型来表示时间戳,但在DynamoDB中并没有这个类型。

  1. 我应该使用什么数据类型?字符串?数字?
    enter image description here

  2. 对于所选择的数据类型,应该采用哪种时间戳格式?ISO格式 (例如:2016-11-11T17:21:07.5272333Z) 或者是纪元时间(例如:1478943038816)?

  3. 我需要通过一段时间范围来搜索表格,例如从2015年1月1日上午10:00:00到2016年12月31日晚上11:00:00


1
https://dev59.com/xV4c5IYBdhLWcg3wdKKT - George Whitaker
2
我们使用一个数字来表示时间戳/格式。除了基本的 customer_id 之外,我们还将其用于范围搜索。 - George Whitaker
可以使用字符串和数字数据类型。在存储ISO8601格式时使用字符串,在存储Epoch时间时使用数字。更多信息请参见:https://www.abhayachauhan.com/2017/12/how-to-store-dates-or-timestamps-in-dynamodb/ - Abhaya Chauhan
1
官方文档指出:“您可以使用字符串数据类型来表示日期或时间戳。一种方法是使用ISO 8601字符串”。(官方文档链接:https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) - Hong
你所复制屏幕截图的答案(https://dev59.com/xV4c5IYBdhLWcg3wdKKT#27894543)回答了这个问题——而这个问题实际上是复制了该答案中提出的问题:https://dev59.com/xV4c5IYBdhLWcg3wdKKT - cellepo
可能是Is it possible to save datetime to DynamoDB?的重复问题。 - cellepo
5个回答

139

使用String数据类型可表示日期或时间戳。

其中一种方法是使用ISO 8601字符串,如下所示:

2016-02-15

2015-12-21T17:42:34Z

20150311T122706Z

DynamoDB用于日期或时间戳的数据类型

是的,在字符串格式存储日期时支持范围查询。可以在FilterExpresssion上使用BETWEEN。我已经使用以下过滤表达式获取了结果中的项目。

不带时间的FilterExpression:-

FilterExpression : 'createdate between :val1 and :val2',
ExpressionAttributeValues : {
        ':hkey' : year_val,
        ':rkey' : title,
        ":val1" : "2010-01-01",
        ":val2" : "2010-12-31"
    }

时间筛选表达式:-

FilterExpression : 'createdate between :val1 and :val2',
    ExpressionAttributeValues : {
        ':hkey' : year_val,
        ':rkey' : title,
        ":val1" : "2010-01-01T00:00:00",
        ":val2" : "2010-12-31T00:00:00"
    }

数据库数值:

格式1 - 包括时区:

{"Item":{"createdate":{"S":"2010-12-21T17:42:34+00:00"},"title":{"S":"The Big New Movie 2010"},"yearkey":{"N":"2010"},"info":{"M":{"rating":{"N":"0"},"plot":{"S":"Nothing happens at all."}}}}}

格式2 - 不带时区:-

{"Item":{"createdate":{"S":"2010-12-21T17:42:34Z"},"title":{"S":"The Big New Movie 2010"},"yearkey":{"N":"2010"},"info":{"M":{"rating":{"N":"0"},"plot":{"S":"Nothing happens at all."}}}}}

@notionquest,你能用字符串进行日期和时间范围搜索吗? - Dennis
2
一个字符串日期可以按ISO 8601格式排序存储,因为8601旨在在相同时区内进行字母数字排序。 - wprl
97
我不明白你为什么会得出“字符串数据类型应该用于日期或时间戳”的结论。文档还说可以通过纪元时间使用数字数据类型来表示日期。那么,为什么你认为应该使用字符串而不是数字呢? - Roly
1
可以使用字符串和数字数据类型。在存储ISO8601格式时使用字符串,在存储Epoch时间时使用数字。更多信息请访问:https://www.abhayachauhan.com/2017/12/how-to-store-dates-or-timestamps-in-dynamodb/ - Abhaya Chauhan
8
@roly 数字也可以使用,但它们不太易读。 - Matthew Bonig
显示剩余7条评论

59

数据类型根据您的需求而定。

您可以使用 ISO 格式的字符串或者使用 epoch 格式的数字。

ISO 格式(字符串)的优点是易于人类阅读,但 DynamoDB 不支持此格式的 Time To Live (TTL)。所有过滤器都可用,例如 'between' 和 'range',如 notionquest 所解释的那样。

对于 DynamoDB,Time To Live(TTL) 允许您定义表中的项目何时过期,以便可以自动从数据库中删除它们。

使用 epoch 格式(数字类型)的优点是可以使用 TTL 功能和所有过滤器。

简而言之;

Epoch 格式(数字类型) - 可以使用 Time To Live
ISO 格式(字符串类型) - 无法使用 Time To Live,但更易读


过滤表达式可能支持数字,但基于范围的键条件仅支持 ISO 格式的字符串。 - Rafael Almeida
@RafaelAlmeida,你是什么意思?你的来源是什么? - Zachary Ryan Smith
1
@ZacharyRyanSmith 我错了 - 实际上,Number 属性可以作为排序键和过滤器中的 Key Conditions。 - Rafael Almeida
但是不可能出现数字位数不同的情况吗?比如搜索时有PK#9999,然后又有PK#10002。这些无法通过范围查询进行过滤。 ISO格式具有固定长度,因此不会出现这个问题... - Worthy7
星期日,2001年9月9日01:46:40 是时代的1000000000秒。 因此,此之前的日期将减少一个数字。如果以字符串形式查询(最有可能是需要与PK#等内容连接),这将使数字版本无法查询。 - Worthy7

16

为了在发送查询请求时过滤结果,我使用了epoch格式的DateTime,这比使用字符串更有效。

想象一下这些场景:过去31天,过去24小时...使用字符串格式也可以实现所有这些场景,因为它还具有begins_with运算符(请查看AWS文档下面链接中的第3个示例),但是数值类型在排序(比较)和计算方面更加高效。

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.KeyConditionExpressions

将日期时间转换为epoch格式很容易。

Javascript:

var date = new Date();
var epoch = date.getTime();

// converting back to date-time
var initial_date = new Date(epoch);

C#

var date = DateTime.UtcNow;
var epoch = new DateTimeOffset(date).ToUnixTimeSeconds();

// converting back to date-time
var initial_date = DateTimeOffset.FromUnixTimeSeconds(epoch);

Python

import time
epoch = time.time()
 
# converting back to date-time
initial_date = time.gmtime(epoch )

6
数字数据类型字符串数据类型可用于日期或时间戳 - 此问题的已接受答案错误地将其单独指出为字符串,而忽略了数字。请注意。
你可以使用数字数据类型来代表日期或时间戳。一种方法是使用纪元时间——自1970年1月1日UTC 00:00:00以来的秒数。例如,纪元时间1437136300表示2015年7月17日UTC下午12:31:40。
更多信息请参见 http://en.wikipedia.org/wiki/Unix_time
...
你可以使用字符串数据类型来代表日期或时间戳。一种方法是使用ISO 8601字符串,如以下示例所示:
2016-02-15 2015-12-21T17:42:34Z 20150311T122706Z
更多信息请参见 http://en.wikipedia.org/wiki/ISO_8601

DynamoDB日期或时间戳的数据类型


1
在DynamoDB中,有几种数据类型可用于存储日期。建议的方法是使用“String”数据类型,并遵循特定的日期格式,例如ISO 8601
以下是在DynamoDB中存储日期的两种常见格式:
ISO 8601格式(例如,“2023-05-23T12:34:56Z”):
此格式以UTC表示日期和时间。它提供了日期的标准和明确的表示,并且可以轻松地按照时间顺序排序。末尾的“Z”表示日期和时间处于UTC中。当您需要执行日期比较或范围查询时,可以使用此格式。
Unix时间戳(例如1674512096):
Unix时间戳表示自1970年1月1日(也称为Unix纪元)以来经过的秒数。将日期存储为Unix时间戳可能在需要执行计算或将其转换为不同时区时很有用。但是,基于Unix时间戳进行排序和查询可能需要额外的处理或索引。

额外的考虑

在选择适当的格式时,请考虑您的应用程序的具体要求。如果您主要需要对日期进行排序、比较或查询,则 ISO 8601 格式通常更适合。例如,假设您想要查找所有创建于2023年9月的项目,那么您可以很容易地使用 ISO 8601 完成此操作,并且具有人类可读性的优势:

SELECT * from MyTable WHERE pk = 'x' AND sk begins_with('2023-09')

另一方面,如果您需要进行计算或时区转换,则将日期存储为 Unix 时间戳可能更可取。如果您希望使用DynamoDB TTL功能,则还需要使用 Unix 时间戳,该功能需要以秒为单位的 unix epoch 数字类型。


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