PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Jaki jest najbardziej zalecany sposób przechowywania czasu w PostgreSQL przy użyciu Javy?

Każda strategia przechowywania danych daty i czasu w PostgreSQL powinna, IMO, opierać się na tych dwóch punktach:

  • Twoje rozwiązanie powinno nigdy zależy od ustawienia strefy czasowej serwera lub klienta.
  • Obecnie PostgreSQL (jak większość baz danych) nie ma typu danych do przechowywania pełnego data i godzina ze strefą czasową. Musisz więc wybrać między Instant lub LocalDateTime typ danych.

Mój przepis jest zgodny.

Jeśli chcesz nagrać fizyczne natychmiastowe kiedy miało miejsce określone wydarzenie (prawdziwa „sygnatura czasowa ”, zazwyczaj jakieś zdarzenie tworzenia/modyfikacji/usuwania), a następnie użyj:

  • Java:Instant (Java 8 lub Jodatime).
  • JDBC:java.sql.Timestamp
  • PostgreSQL:TIMESTAMP WITH TIMEZONE (TIMESTAMPTZ )

(Nie zezwalaj na specyficzne typy danych PostgreSQL WITH TIMEZONE /WITHOUT TIMEZONE mylić:żaden z nich nie przechowuje strefy czasowej)

Jakiś standardowy kod:poniżej zakłada się, że ps jest PreparedStatement , rs ResultSet i tzUTC jest statycznym Calendar obiekt odpowiadający UTC strefa czasowa.

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

Napisz Instant do bazy danych TIMESTAMPTZ :

Instant instant = ...;
Timestamp ts = instant != null ? Timestamp.from(instant) : null;
ps.setTimestamp(col, ts, tzUTC);   // column is TIMESTAMPTZ!

Przeczytaj Instant z bazy danych TIMESTAMPTZ :

Timestamp ts = rs.getTimestamp(col,tzUTC); // column is TIMESTAMPTZ
Instant inst = ts !=null ? ts.toInstant() : null;

Działa to bezpiecznie, jeśli Twój typ PG to TIMESTAMPTZ (W takim przypadku calendarUTC nie ma wpływu na ten kod; ale zawsze zaleca się, aby nie polegać na domyślnych strefach czasowych). „Bezpiecznie” oznacza, że ​​wynik nie będzie zależał od strefy czasowej serwera lub bazy danych , lub informacje o strefach czasowych:operacja jest w pełni odwracalna i cokolwiek stanie się z ustawieniami stref czasowych, zawsze uzyskasz ten sam „chwilowy moment”, który miałeś pierwotnie po stronie Java.

Jeśli zamiast znacznika czasu (chwila na fizycznej osi czasu) masz do czynienia z "cywilną" lokalną datą i godziną (czyli zestaw pól {year-month-day hour:min:sec(:msecs)} ), użyjesz:

  • Java:LocalDateTime (Java 8 lub Jodatime).
  • JDBC:java.sql.Timestamp
  • PostgreSQL:TIMESTAMP WITHOUT TIMEZONE (TIMESTAMP )

Przeczytaj LocalDateTime z bazy danych TIMESTAMP :

Timestamp ts = rs.getTimestamp(col, tzUTC); //
LocalDateTime localDt = null;
if( ts != null ) 
    localDt =  LocalDateTime.ofInstant(Instant.ofEpochMilli(ts.getTime()), ZoneOffset.UTC);

Napisz LocalDateTime do bazy danych TIMESTAMP :

  Timestamp ts = null;
  if( localDt != null)    
      ts = new Timestamp(localDt.toInstant(ZoneOffset.UTC).toEpochMilli()), tzUTC);
  ps.setTimestamp(colNum,ts, tzUTC); 

Ponownie, ta strategia jest bezpieczna i możesz spać spokojnie:jeśli zapisałeś 2011-10-30 23:59:30 , będziesz pobierać te dokładne pola (godzina=23, minuta=59... itd.) zawsze, bez względu na wszystko — nawet jeśli jutro zmieni się strefa czasowa serwera (lub klienta) Postgresql, strefa czasowa JVM lub systemu operacyjnego, lub jeśli twój kraj modyfikuje zasady czasu letniego itp.

Dodano:Jeśli chcesz (wydaje się to naturalnym wymogiem) przechowywać pełną specyfikację daty i godziny (ZonedDatetime :znacznik czasu wraz ze strefą czasową, która domyślnie zawiera również pełną cywilną informację o dacie i godzinie - plus strefę czasową)... to mam dla ciebie złą wiadomość:PostgreSQL nie ma dla tego typu danych (ani inne bazy danych, o ile mi wiadomo) . Musisz wymyślić własne miejsce do przechowywania, być może w parze pól:mogą to być dwa powyższe typy (wysoce nadmiarowe, ale wydajne do wyszukiwania i obliczania) lub jeden z nich plus przesunięcie czasowe (tracisz informacje o strefie czasowej, niektóre obliczenia stają się trudne, a niektóre niemożliwe) lub jeden z nich plus strefa czasowa (jako ciąg; niektóre obliczenia mogą być niezwykle kosztowne).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak stworzyć tymczasową funkcję w PostgreSQL?

  2. Wstawianie ciągu tekstowego z szesnastką do PostgreSQL jako bajt

  3. Praca w kierunku Postgres-XL 9,5

  4. Nie można połączyć postgreSQL z psycopg2

  5. Jak obliczyć wykładniczą średnią kroczącą na postgresie?