sql >> データベース >  >> RDS >> PostgreSQL

Javaを使用してPostgreSQLに時間を保存するための最も推奨される方法は何ですか?

    PostgreSQLに日付と時刻のデータを保存するための戦略は、IMOが次の2つの点に依存する必要があります。

    • ソリューションは絶対にすべきではありません サーバーまたはクライアントのタイムゾーン設定によって異なります。
    • 現在、PostgreSQL(ほとんどのデータベースと同様)には、フルを格納するためのデータ型がありません。 タイムゾーン付きの日時。したがって、Instantのどちらかを決定する必要があります またはLocalDateTime データ型。

    私のレシピは次のとおりです。

    物理的なインスタントを記録する場合 特定のイベントが発生したとき(真の「タイムスタンプ "、通常は作成/変更/削除イベント)、次に使用します:

    • Java:Instant (Java 8、またはJodatime)。
    • JDBC:java.sql.Timestamp
    • PostgreSQL:TIMESTAMP WITH TIMEZONETIMESTAMPTZ

    (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 ? Timestamp.from(instant) : null;
    ps.setTimestamp(col, ts, tzUTC);   // column is TIMESTAMPTZ!
    

    Instantを読む データベースからTIMESTAMPTZ

    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)} )、使用します:

    • Java:LocalDateTime (Java 8、またはJodatime)。
    • JDBC:java.sql.Timestamp
    • PostgreSQL:TIMESTAMP WITHOUT TIMEZONETIMESTAMP

    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を保存した場合 、これらの正確なフィールド(hour =23、minute =59 ...など)は、いつでも取得できます。たとえ明日、Postgresqlサーバー(またはクライアント)のタイムゾーンが変更されたり、JVMまたはOSのタイムゾーンが変更されたりしても、または、お住まいの国がDSTルールなどを変更した場合。

    追加:完全な日時指定(ZonedDatetime)を保存したい場合(当然の要件のようです) :タイムスタンプとタイムゾーン(完全な市民日時情報とタイムゾーンも暗黙的に含まれています)...それでは悪いニュースがあります:PostgreSQLにはこのデータ型がありません(私の知る限り、他のデータベースでもありません) 。おそらくフィールドのペアで、独自のストレージを考案する必要があります。上記の2つのタイプ(非常に冗長ですが、取得と計算には効率的です)、またはそれらの1つにタイムオフセットを加えたもの(タイムゾーン情報が失われ、一部の計算は次のようになります)になります。困難で、一部は不可能です)、またはそれらの1つとタイムゾーン(文字列として。一部の計算は非常にコストがかかる可能性があります)。



    1. PostgreSQLのカーソルベースのレコード

    2. SqlConnection SqlCommand SqlDataReader IDisposable

    3. LAST_DAY()がMariaDBでどのように機能するか

    4. LinuxターミナルでのMySQLの使用の簡単な紹介