java - 使用 Java 在 PostgreSQL 中存储时间的最推荐方法是什么?

标签 java postgresql date jdbc

我在 PostgreSQL 数据库中存储了两个日期。第一个是网页的访问数据,第二个日期是网页最后一次修改的日期(这个是get as long)。

我有些怀疑存储这些值的最佳策略是什么。

我只需要日/月/年和小时:秒,这仅用于统计建议。

所以,有些疑问:

  • 最好存储时间长并在恢复信息时进行转换,还是以上述数据格式存储?
  • 最好是在软件上设置访问日期还是在数据库中插入?
  • 在 Java 中,处理日期的最佳类是什么?

最佳答案

任何在 PostgreSQL 中存储日期和时间数据的策略,IMO,都应该依赖于这两点:

  • 您的解决方案应该从不依赖于服务器或客户端的时区设置。
  • 目前,PostgreSQL(与大多数数据库一样)没有数据类型来存储带有时区的完整日期和时间。因此,您需要在 Instant 之间做出决定或 LocalDateTime数据类型。

我的食谱如下。


如果您想记录特定事件发生时的物理瞬间(真正的“时间戳”,通常是一些创建/修改/删除事件),那么使用:

(不要让 PostgreSQL 特殊的数据类型 WITH TIMEZONE/WITHOUT TIMEZONE 迷惑你:它们实际上都没有存储时区)

一些样板代码:以下假设 psPreparedStatementrsResultSettzUTC 是一个静态 Calendar 对象,对应于 UTC 时区。

public static final Calendar tzUTC = Calendar.getInstance(TimeZone.getTimeZone("UTC"));  

Instant写入数据库TIMESTAMPTZ:

Instant instant = ...;
Timestamp ts = instant != null ? Timestamp.from(instant) : null;
ps.setTimestamp(col, ts, tzUTC);   // column is TIMESTAMPTZ!

从数据库TIMESTAMPTZ中读取Instant:

Timestamp ts = rs.getTimestamp(col,tzUTC); // column is TIMESTAMPTZ
Instant inst = ts !=null ? ts.toInstant() : null;

如果您的 PG 类型是 TIMESTAMPTZ,这将安全工作(在这种情况下,calendarUTC 在该代码中无效;但始终建议不要依赖默认时区)。 “安全”意味着结果将不依赖于服务器或数据库时区,或时区信息:操作是完全可逆的,无论时区设置发生什么,您将始终获得相同的“即时时间”,你最初在 Java 端有。


如果您处理的是“公民”本地日期时间(即字段集{year -month-day hour:min:sec(:msecs)}),你会使用:

从数据库TIMESTAMP中读取LocalDateTime:

Timestamp ts = rs.getTimestamp(col, tzUTC); //
LocalDateTime localDt = null;
if( ts != null ) 
    localDt =  LocalDateTime.ofInstant(Instant.ofEpochMilli(ts.getTime()), ZoneOffset.UTC);

LocalDateTime写入数据库TIMESTAMP:

  Timestamp ts = null;
  if( localDt != null)    
      ts = new Timestamp(localDt.toInstant(ZoneOffset.UTC).toEpochMilli()), tzUTC);
  ps.setTimestamp(colNum,ts, tzUTC); 

同样,这种策略是安全的,您可以安然休眠:如果您存储了 2011-10-30 23:59:30 ,您将检索到那些精确的字段(小时=23,分钟= 59...等),无论如何 - 即使明天您的 Postgresql 服务器(或客户端)的时区发生变化,或者您的 JVM 或您的操作系统时区,或者您的国家/地区修改其 DST 规则等。


添加:如果您想要(这似乎是一个自然的要求)存储完整的日期时间规范(ZonedDatetime:时间戳和时区,其中隐含地还包括完整的民用日期时间信息 - 加上时区).. . 那么我有个坏消息要告诉你:PostgreSQL 没有这种数据类型(据我所知,其他数据库也没有)。您必须设计自己的存储,可能在一对字段中:可能是上述两种类型(高度冗余,但对于检索和计算很有效),或者其中一种加上时间偏移(您丢失时区信息,一些计算变成困难,有些不可能),或者其中之一加上时区(作为字符串;一些计算可能非常昂贵)。

关于java - 使用 Java 在 PostgreSQL 中存储时间的最推荐方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6627289/

相关文章:

java - Jaxb 和 StringBuffer 哪一个在 Xml 字符串创建方面具有更好的性能?

java - 我只想在多级继承中调用子类构造函数?

javascript - 如何完整获取星期几?

java - 处理结果集中每一行的新日历/日期实例

java - Apache POI中如何自动区分XSSF和HSSF?

python - 一次将 API 响应插入多行 - psycopg2

sql - 合并两列并添加到一个新列中

php - 使用 Postgresql 的 Symfony 2

javascript - JS : new Date() is not accepting date string in my own locale (d/m/y)

部署小程序时,Glassfish 中出现 java.lang.reflect.InitationTargetException