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

如果要记录特定事件(通常是某些创建/修改/删除)发生的物理瞬间(一个真正的“时间戳”),我建议:

> Java:java.util.Date类 – 或者,如果使用,Jodatime(强烈推荐),即时。

> JDBC:java.sql.Timestamp

> Postgresql:TIMESTAMP WITH TIMEZONE(TIMESTAMPTZ)

(不要被Postgresql数据类型名称所迷惑:WITH TIMEZONE / WITHOUT TIMEZONE有非常特殊的含义,其中没有一个实际存储时区)

这种情况的一些样板代码:以下假设ps是一个PreparedStatement,rs一个ResultSet和calendarUTC是一个对应于UTC的静态Calendar对象。

写入数据库:

long milis = date.getTime() ; // or instant.getMillis() or whatever

ps.setTimestamp(colNum,new Timestamp(milis), calendarUTC); // column is TIMESTAMPTZ!

从数据库读取:

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

...

Timestamp ts = rs.getTimestamp(colnum,tzUTC); // column is TIMESTAMPTZ

return ts !=null ? new Date(ts.getTime) : null;

如果你的PG类型是TIMESTAMPTZ(在这种情况下,calendarUTC对该代码没有影响,但是总是建议不依赖于默认的时区),这样做是安全的。

“安全”意味着结果不依赖于服务器或数据库时区或时区信息:操作是完全可逆的,无论时区设置如何,您将始终获得相同的“即时时间”。

如果您想要安全地记录“民用”本地日期时间(即,整个月份 – 日 – 小时 – 分钟)字段,而不是时间戳(物理时间线上的即时时间)您应该使用TIMESTAMP WITHOUTZONE并使用稍微不同的逻辑。为了完整起见(这里我使用Joda的LocalDateTime; Java的Date API是痛苦的)。

从数据库读取:

public static final DateTimeZone jodaTzUTC = DateTimeZone.forID("UTC");

...

Timestamp ts = getter.getTimestamp(tzUTC);

return ts != null ? new LocalDateTime(ts.getTime(), jodaTzUTC ) : null;

写入数据库:

Timestamp ts = new Timestamp(localdatime.toDateTime(jodaTzUTC).getMillis())

ps.setTimestamp(colNum,ts, tzUTC); // column is TIMESTAMP !

再次,这个策略是安全的,你可以安心地睡觉:如果你们存储“2011-10-30 23:59:30”,你将总是检索这些精确的字段(年= 2011,月= 10 …等等) ,无论什么,即使明天有人更改Postgresql,JVM或OS时区的时区,或者您的国家更新其DST规则等。

添加:如果您希望(似乎是一个自然需求)来存储完整的datetime规范(Jodatime中的Datetime:时间戳与时区,这也隐含地包括完整的民事日期时间信息加上时区),您已经不在运气:Postgresql没有一个数据类型(对我而言,其他数据库都不知道)。您必须设计自己的存储空间,也许在一对领域中:可以是上述两种类型(高度冗余,尽管有效的检索和计算),或者其中一个加上时间偏移(您丢失时区信息,一些计算成为困难和一些不可能),或其中一个加上时区(作为字符串;一些计算可能是非常昂贵的)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值