将数据库中的日期存储为数据库的Java最佳做法是什么?

时间:2012-11-09 07:09:08

标签: java sql mongodb date timestamp

我这样做的原因是,在任何数据库中存储为日期对象的日期往往以特定格式编写,这可能与您在前端向用户呈现的内容大不相同。我还认为,如果您的应用程序从不同类型的数据存储中提取信息,这将特别有用。一个很好的例子是MongoDB和SQL日期对象之间的区别。

但是,我不知道这是否是推荐的做法。我应该将日期保存为长(以毫秒为单位)或作为日期对象吗?

6 个答案:

答案 0 :(得分:23)

我不能代表MongoDB发言,但在SQL数据库中,不,这不是最佳实践。这并不意味着可能没有偶尔的用例,而是“最佳实践”,没有。

将它们存储为日期,将其作为日期检索。您最好的办法是设置数据库以将它们存储为UTC(松散地,“GMT”),以便数据是可移植的,并且您可以根据需要使用不同的本地时间(例如,如果数据库由地理位置不同的用户使用) ,并处理从应用程序层到UTC的本地时间的任何转换(例如,通过Calendar或第三方日期库)。

将日期存储为数字意味着您的数据库很难报告,运行即席查询等等。我犯了一次错误,但如果没有真的这么好的理由我就不会重复。 : - )

答案 1 :(得分:5)

这在很大程度上取决于:

  • 您正在使用的数据库及其日期/时间支持
  • 您的客户需要(例如,您是否愿意接受总是使用Java的想法)
  • 您真正想要表达的信息
  • 您的诊断工具

第三点可能是最重要的。想想你试图存储的价值究竟是什么意思。即使您显然没有使用Noda Time,但希望我的user guide page on choosing which Noda Time type to use基于您的输入数据可以帮助您清楚地思考这一点。

如果曾经使用过Java,而您的数据库对日期/时间类型没有非常好的支持,而您只是想表示一个“即时”(而不是,比如说,特定时区的瞬间,或带偏移的本地日期/时间,或只是当地日期/时间,或只是一个日期......),你'很乐意编写诊断工具将数据转换为更易读的形式 - 然后存储long是合理的。但这是一个很长的“如果”的清单。

如果您希望能够在数据库中执行日期操作 - 例如要求在该月的第一天发生的所有值 - 那么您应该使用日期/时间类型,在时区周围小心。 (我的经验是,大多数数据库在日期/时间类型方面至少令人震惊记录。)

通常,您应该使用能够满足所有要求的任何类型,并且是该特定环境的自然表示。因此,在具有日期/时间类型的数据库中,当您与其进行交互时不会出现问题(例如,以未请求的方式执行任意时区转换),请使用该类型。它会使各种事情变得更容易。

使用更“原始”表示(例如64位整数)的优点正是数据库不会乱用它。你有效地隐藏了数据库中数据的含义,并且具有该方法的所有正常优点和缺点(主要是缺点)。

答案 2 :(得分:1)

这取决于各方面。当使用标准的“自纪元以来的秒数”,并且有人仅使用整数精度时,它们的日期限制在1970 - 2038年范围内。

但也存在一些精确问题。例如,unix time 忽略闰秒。每天定义为具有相同的秒数。因此,当计算unix时间之间的时间增量时,你会收到一些错误。

但更重要的是,你假设所有日期都是完全已知的,因为你的代表不可能只有半个指定日期的一半。实际上,有很多事件你不知道在第二(甚至ms)精度。因此,如果表示允许指定例如,则这是一个特征。只有精度。理想情况下,您可以使用其精确信息存储日期。

此外,假设您正在构建日历应用程序。有时间,但也有当地时间。通常,您需要两种信息。当安排重叠时,你当然可以在同步的时间内做到最好,所以在这里很长一段时间。但是,如果您还希望确保不在9-20小时当地时间之外安排活动,则还需要保留时区信息。对于任何跨越多个位置的内容,您确实需要在日期表示中包含时区。假设您可以将您看到的所有日期转换为您当前的当地时间是非常幼稚的。

请注意,SQL中的日期可能导致奇怪的情况。我最喜欢的一个是以下 MySQL荒谬

SELECT * FROM Dates WHERE date IS NULL AND date IS NOT NULL;

可能会返回日期为0000-00-00 00:00:00的记录,但这违反了对逻辑的普遍理解。

答案 3 :(得分:1)

由于这个问题是用MongoDB标记的:MongoDB不会将日期存储在String中或者不存储,它们实际上将它存储为long(http://www.mongodb.org/display/DOCS/Dates):

  

BSON Date值将自Unix纪元(1970年1月1日)以来的毫秒数存储为64位整数。 v2.0 +:此号码已签名,因此1970年之前的日期将存储为负数。

由于MongoDB没有立即计划利用复杂的日期处理函数(比如只获得一年的查询等),SQL在标准查询中没有真正的缺点,它可能会减少索引和存储的大小。 / p>

这里有一件事需要考虑,聚合框架:http://docs.mongodb.org/manual/reference/aggregation/#date-operators只有MongoDB中支持的BSON日期类型才有奇怪而奇妙的东西,但是,这对你来说是否重要取决于根据您的疑问。

您是否认为自己需要聚合框架功能?或者容纳额外的物体开销是一种痛苦?

我个人认为,BSON日期类型是一个很小的对象,如果没有它就可以存储一个文件,这对于整个系统及其未来的兼容性没有明显的原因。所以,是的,我会使用BSON日期类型而不是长期,我认为这样做是好的做法。

答案 4 :(得分:0)

我不认为将日期存储的最佳做法是因为,这意味着您将无法执行任何特定日期的查询。喜欢:

where date between 

我们也无法轻松地使用SQL查询从表中获取一年中的日期月份。

最好在java图层中使用单个日期格式转换器,并将日期转换为该日期,并在整个应用程序中使用单一格式。

答案 5 :(得分:-3)

恕我直言,如果你可以使用字符串,最好在DB中存储日期。因此,如果您不需要日历中的所有字段,请避免不必要的数据上下移动到服务器。 日历中有很多数据,每个Calender实例都非常重要。

因此,将它存储为String,仅包含所需数据,并在需要时将其转换回日历并使用它们。