Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Java在PostgreSQL中存储时间的最推荐方法是什么?_Java_Postgresql_Date_Jdbc - Fatal编程技术网

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

使用Java在PostgreSQL中存储时间的最推荐方法是什么?,java,postgresql,date,jdbc,Java,Postgresql,Date,Jdbc,我在PostgreSQL数据库中存储了两个日期。首先是网页访问的数据,第二个日期是网页最后一次修改的日期(这是一个很长的日期) 我怀疑什么是存储这些价值的最佳策略 我只需要天/月/年和小时:秒,这将仅用于统计建议 因此,有一些疑问: 最佳存储是否与恢复信息时一样长并转换,还是以上述数据格式存储 最好是在软件上设置访问日期,还是在数据库中插入 在Java中,处理日期的最佳类是什么 我认为,在PostgreSQL中存储日期和时间数据的任何策略都应该依赖以下两点: 您的解决方案不应依赖于服务器或客

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

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

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

因此,有一些疑问:

  • 最佳存储是否与恢复信息时一样长并转换,还是以上述数据格式存储
  • 最好是在软件上设置访问日期,还是在数据库中插入
  • 在Java中,处理日期的最佳类是什么
我认为,在PostgreSQL中存储日期和时间数据的任何策略都应该依赖以下两点:

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


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

  • Java:(Java8或Jodatime)
  • JDBC:
    java.sql.Timestamp
  • PostgreSQL:(
    TIMESTAMPTZ
(不要让带有时区的PostgreSQL特有的数据类型
,而不带时区的数据类型
迷惑你:它们实际上都没有存储时区)

一些样板代码:以下假设
ps
是一个
PreparedStatement
rs
a
ResultSet
tzUTC
是一个与
UTC
时区相对应的静态
Calendar
对象

public static final Calendar tzUTC = Calendar.getInstance(TimeZone.getTimeZone("UTC"));  
Instant
写入数据库
TIMESTAMPTZ

Instant instant = ...;
Timestamp ts = instant != null ? new Timestamp(instant.toEpochMilli()) : null;
ps.setTimestamp(col, ts, tzUTC);   // column is TIMESTAMPTZ!
Timestamp ts = rs.getTimestamp(col,tzUTC); // column is TIMESTAMPTZ
Instant inst = ts !=null ? Instant.ofEpochMilli(ts.getTime()) : null;
从数据库
TIMESTAMPTZ
读取
Instant

Instant instant = ...;
Timestamp ts = instant != null ? new Timestamp(instant.toEpochMilli()) : null;
ps.setTimestamp(col, ts, tzUTC);   // column is TIMESTAMPTZ!
Timestamp ts = rs.getTimestamp(col,tzUTC); // column is TIMESTAMPTZ
Instant inst = ts !=null ? Instant.ofEpochMilli(ts.getTime()) : null;
如果您的PG类型为
timestamtz
(在这种情况下,
calendarUTC
在该代码中无效;但始终建议不要依赖默认时区)。 “安全”意味着结果将不依赖于服务器或数据库时区或时区信息:该操作是完全可逆的,无论时区设置发生什么变化,您将始终获得与Java端相同的“时间瞬间”


如果您处理的不是时间戳(物理时间轴上的一个瞬间),而是“civil”本地日期时间(即,字段集
{year-month-day-hour:min:sec(:msecs)}
),则您将使用:

  • Java:(Java8或Jodatime)
  • JDBC:
    java.sql.Timestamp
  • PostgreSQL:(
    时间戳
从数据库中读取
LocalDateTime

Timestamp ts = rs.getTimestamp(col, tzUTC); //
LocalDateTime localDt = null;
if( ts != null ) 
    localDt =  LocalDateTime.ofInstant(Instant.ofEpochMilli(ts.getTime()), ZoneOffset.UTC);
  Timestamp ts = null;
  if( localDt != null)    
      ts = new Timestamp(localDt.toInstant(ZoneOffset.UTC).toEpochMilli()), tzUTC);
  ps.setTimestamp(colNum,ts, tzUTC); 
LocalDateTime
写入数据库
TIMESTAMP

Timestamp ts = rs.getTimestamp(col, tzUTC); //
LocalDateTime localDt = null;
if( ts != null ) 
    localDt =  LocalDateTime.ofInstant(Instant.ofEpochMilli(ts.getTime()), ZoneOffset.UTC);
  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规则,等等


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

java.time 这并不漂亮,但这正是我在使用Java 8和更高版本()中的新框架的实例中所做的工作:


“date”这个词的意思太多了,但它最常见的意思是年-月-日,没有时间。也许你最好在文章标题和正文中说“datetime”或“timestamp”。(a)这个答案并不完全符合问题的意图。(b)这段代码有一种更直接的方法。旧的类,如
java.sql.Timestamp
在java 8和更高版本中进行了改进,使用方便的方法转换为新的java.time类型。因此:
java.sql.Timestamp ts=java.sql.Timestamp.fromInstant(myZonedDateTime.toInstant())
答案很好,但在Java 8及更高版本中已经过时,我们现在有了内置框架(灵感来自Joda Time)@BasilBourque,我从未使用过JodaTime,我刚刚开始使用Java 8。对我来说,这个答案与Java 8 API几乎是1比1。我不能确定yoda,但在使用Java 8 Instant时,你不应该用TZ保存时间戳。Instant是UTC。时间戳也是UTC。它不需要TZ,保存它可能会导致错误。我为此付出了很多代价ral hours,使用Jooq,因为它正确地写入了timestamtz,但在读取值时没有按照预期使用时区。关于时区文字的存储,我的问题由Craig Ringer回答,可能也有帮助:。存储客户端最初在瞬间选择的时区是一个好主意,尤其是f或日历应用程序。@mlorber我意识到您的评论很旧,但不正确,您肯定应该在几乎所有情况下使用带有tz的时间戳。我建议阅读。注意:您确实需要将JVM设置为UTC,以便postgres正确解释传入的字符串。