PostgreSQLデータベースに2つの日付を保存しています。 1つ目はWebページの訪問データであり、2つ目の日付はWebページの最終変更日です(これは長くなります)。
これらの値を保存するための最善の戦略は何か疑問があります。
私は日/月/年と時:秒のみが必要であり、これは統計的な提案のためだけです。
だから、いくつかの疑問:
日時データをPostgreSQLに保存するための戦略は、IMOが次の2つの点に依存する必要があります。
Instant
または LocalDateTime
データタイプのいずれかを決定する必要があります。私のレシピが続きます。
特定のイベントが発生したときに物理的なインスタントを記録したい場合は、(真の "timestamp"、通常は作成/変更/削除イベント)、次に使用:
Instant
(Java 8またはJodatime)。Java.sql.Timestamp
_TIMESTAMP WITH TIMEZONE
_ (TIMESTAMPTZ
)(PostgreSQLに特有のデータ型_WITH TIMEZONE
_/_WITHOUT TIMEZONE
_を混同させないでください:それらのどれも実際にタイムゾーンを保存しません)
定型コード:ps
はPreparedStatement
、rs
はResultSet
、tzUTC
は静的Calendar
UTC
タイムゾーンに対応するオブジェクト。
_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!
_
データベースInstant
からTIMESTAMPTZ
を読み取ります。
_Timestamp ts = rs.getTimestamp(col,tzUTC); // column is TIMESTAMPTZ
Instant inst = ts !=null ? Instant.ofEpochMilli(ts.getTime()) : null;
_
PGタイプがTIMESTAMPTZ
の場合、これは安全に機能します(その場合、calendarUTC
はそのコードには影響しませんが、デフォルトのタイムゾーンに依存しないことを常にお勧めします)。 「安全」とは、結果がサーバーまたはデータベースのタイムゾーンまたはタイムゾーン情報に依存しないことを意味します。操作は完全に可逆であり、タイムゾーン設定に何が起こっても、常に取得できます。 Java側で最初に持っていたのと同じ「インスタント」。
タイムスタンプ(物理タイムライン上のインスタント)ではなく、 "civil" local date-time(つまり、フィールドのセット{year-month-day hour:min:sec(:msecs)}
)、使用します:
LocalDateTime
(Java 8またはJodatime)。Java.sql.Timestamp
_TIMESTAMP 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);
_
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またはOSのタイムゾーン、または国がDSTルールなどを変更した場合.
追加:必要に応じて(当然のことと思われますが)完全な日時指定を保存します( ZonedDatetime
:タイムゾーンとタイムゾーン、暗黙的に完全な市民日時情報も含みます) -プラスタイムゾーン)...それから私はあなたに悪いニュースがあります:PostgreSQLにはこれのデータ型がありません(私の知る限り、他のデータベースもありません)。おそらく一対のフィールドに独自のストレージを考案する必要があります:上記の2つのタイプ(非常に冗長で、検索と計算に効率的)、またはそれらの1つとタイムオフセット(タイムゾーン情報を失い、一部の計算は困難で、一部は不可能)、またはそれらの1つとタイムゾーン(文字列として、一部の計算は非常に高価になる可能性があります)。
それはきれいではありませんが、これは新しい Java.time フレームワークを使用して ZonedDateTime
インスタンスで私のために働いたものですin Java 8以降( Tutorial )):
ZonedDateTime receivedTimestamp = some_ts_value;
Timestamp ts = new Timestamp(receivedTimestamp.toInstant().toEpochMilli());
ps.setTimestamp(
1,
ts,
Calendar.getInstance(TimeZone.getTimeZone(receivedTimestamp.getZone()))
);
つかいます Java.util.Date
でJavaアプリケーションとtimestamp with time zone
データベース内。