在 DynamoDB 中处理 Java8 日期和时间的最佳方法

Best approach to handle Java8 date and time in DynamoDB

我研究了使用 Java SDK 存储日期和时间的 DynamoDB 选项。据我所知,Java8 LocalDate 和 LocalDateTime 需要自定义转换器,而对于旧日期、日历和 Joda 时间 LocalDateTime,有一些注释。

根据文档,@DynamoDBTypeConvertedTimestamp 支持标准日期类型转换,例如 java.util.Calendar、Long。 @DynamoDBTypeConvertedEpochDate 可用于将日期、日历和 org.joda.time.DateTime 转换为数值。

同时,如果我不在 Date 字段上放置任何注释,它会被保存,就像上面有 @DynamoDBTypeConvertedTimestamp 一样,甚至范围查询也能成功。

是否有人知道解释不同的可能方法,并就从 DynamoDB 存储和检索 Java 日期和时间对象的最佳方法发表意见?

TLDR;这取决于日期、时间等将如何使用。

长答案

这将取决于您的用例,因此没有硬性的 "best" 方法。但是,需要牢记一些注意事项。

您的 table 架构中使用的值如何?

如果 Java 8 date/time 将用作排序键,请考虑使用自定义转换器将其转换为字符串。如果这样做,则可以在查询的关键条件表达式中使用 begins_with 运算符,例如 begins_with(myDate, "2018-12")。如果您想搜索特定年、月、日、小时等的所有内容,能够像这样查询将使您的代码简单得多

如果您将该值用作 DynamoDB TTL 属性,则必须将其转换为数字时间戳。这是使用 TTL 功能的要求。

我们在谈论 java.time 类 中的哪一个?

Some of the classes in the java.time package 没有自然的数字转换。例如,LocalDate 充其量也很难转换为数字。 LocalDate 2018-12-10 转换为 20181210 最有意义,但在这一点上,您必须编写足够多的代码,您也可以只使用内置的 LocalDate.toString()LocalDate.parse().

您需要多久查看一次数据库以查找错误或修复错误数据?

如果您经常在数据库中乱搞(希望不是这种情况),请使用人类可读的内容。当他们在半夜被呼叫时,没有人愿意弄清楚 2018-12-05T17:23:19.483+08:30 是在 1544572463 之前还是之后。

您的应用程序对增加的延迟有多敏感?

我没有观察到 DynamoDB 在将日期存储为字符串与数字方面有任何可衡量的性能差异。但是,string parsing is slower that using a number 会创建一个 java.time 对象,因此如果将日期存储为字符串,可能会对您的应用程序产生轻微影响。

别让自定义转换器吓跑了你

java.time api 编写它们真的很容易。以下是如何实现 LocalDateTime 的转换器,将其转换为 String.

public class LocalDateTimeToStringTypeConverter implements DynamoDBTypeConverter<String, LocalDateTime> {

    @Override
    public String convert(LocalDateTime localDateTime) {
        return localDateTime.toString();
    }

    @Override
    public LocalDateTime unconvert(String s) {
        return LocalDateTime.parse(s);
    }
}

尝试使用@DynamoDBTyped 注释日期字段,这是一个覆盖 dynamoDB 中标准属性类型绑定的注释。所以它会将日期转换为 Attribute Type = S ,这在 DynamoDM 中是 String 。希望对你有帮助

@DynamoDBTyped(DynamoDBAttributeType.S)
private LocalDate startDate;