Ren*_*ani 48 java postgresql date jdbc
我在PostgreSQL数据库中存储了两个日期.首先,是网页的访问数据,第二个日期是网页的最后修改日期(这是长的).
我怀疑存储这些值的最佳策略是什么.
我只需要日/月/年和小时:秒,这只适用于统计建议.
所以有些疑惑:
leo*_*loy 82
在Postgresql中存储日期和时间数据的任何策略都应该依赖于这两点:
Instant或一个LocalDateTime数据类型之间做出决定.我对每个场景的配方:
如果要记录特定事件(通常是某些创建/修改/删除)的物理瞬间,(真正的" 时间戳 "),则使用:
InstantJava 8,或Jodatime).java.sql.TimestampTIMESTAMP WITH TIMEZONE(TIMESTAMPTZ)(不要让Postgresql特有的数据类型WITH TIMEZONE/ WITHOUT TIMEZONE混淆你:它们中没有一个实际存储时区)
一些样板代码:以下假设ps是a PreparedStatement,rsa ResultSet并且tzUTC是Calendar与UTC时区对应的静态对象.
public static final Calendar tzUTC = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Run Code Online (Sandbox Code Playgroud)
写入Instant数据库TIMESTAMPTZ:
Instant instant = ...;
Timestamp ts = instant != null ? new Timestamp(instant.toEpochMilli()) : null;
ps.setTimestamp(col, ts, tzUTC); // column is TIMESTAMPTZ!
Run Code Online (Sandbox Code Playgroud)
Instant从数据库中读取TIMESTAMPTZ:
Timestamp ts = rs.getTimestamp(col,tzUTC); // column is TIMESTAMPTZ
Instant inst = ts !=null ? Instant.ofEpochMilli(ts.getTime()) : null;
Run Code Online (Sandbox Code Playgroud)
如果您的PG类型是安全的,那么这种方法是安全的TIMESTAMPTZ(在这种情况下,该calendarUTC代码没有任何影响;但总是建议不依赖于默认时区)."安全"意味着结果将不依赖于服务器或数据库时区或时区信息:操作是完全可逆的,无论时区设置发生什么,您将始终获得与原始时间相同的"时刻". Java方面.
如果您有一个"民用"本地日期时间(即字段集{year-month-day hour:min:sec(:msecs)}),而不是时间戳(物理时间轴上的瞬间),则应使用
LocalDateTimeJava 8,或Jodatime).java.sql.TimestampTIMESTAMP WITHOUT TIMEZONE(TIMESTAMP)LocalDateTime从数据库中读取TIMESTAMP:
Timestamp ts = rs.getTimestamp(col, tzUTC); //
LocalDateTime localDt = null;
if( ts != null )
localDt = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts.getTime()), ZoneOffset.UTC);
Run Code Online (Sandbox Code Playgroud)
写入LocalDateTime数据库TIMESTAMP:
Timestamp ts = null;
if( localDt != null)
ts = new Timestamp(localDt.toInstant(ZoneOffset.UTC).toEpochMilli()), tzUTC);
ps.setTimestamp(colNum,ts, tzUTC);
Run Code Online (Sandbox Code Playgroud)
再次,这个策略是安全的,你可以安静地睡觉:如果你存储2011-10-30 23:59:30,你将总是检索那些精确的字段(小时= 23,分钟= 59 ......等),无论如何 - 即使明天你的Postgresql的时区服务器(或客户端)更改,或您的JVM或操作系统时区,或者您的国家/地区修改其DST规则等.
补充:如果你想(似乎是一个自然要求)存储完整的日期时间规范(a ZonedDatetime:时间戳和时区,隐含地还包括完整的民用日期时间信息 - 加上时区),那么你运气不好: Postgresql没有这方面的数据类型(据我所知,这两个数据库都没有).您必须设计自己的存储,可能是在一对字段中:可能是上述两种类型(高度冗余,虽然检索和计算有效),或者其中一种加上时间偏移(您丢失了时区信息,一些计算成为困难,有些不可能),或其中一个加上时区(作为字符串;一些计算可能非常昂贵).
这并不漂亮,但这是在 Java 8 及更高版本(教程)中ZonedDateTime使用新的java.time框架的实例对我有用的方法:
ZonedDateTime receivedTimestamp = some_ts_value;
Timestamp ts = new Timestamp(receivedTimestamp.toInstant().toEpochMilli());
ps.setTimestamp(
1,
ts,
Calendar.getInstance(TimeZone.getTimeZone(receivedTimestamp.getZone()))
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
50962 次 |
| 最近记录: |