sql >> Database teknologi >  >> RDS >> PostgreSQL

Hvad er den mest anbefalede måde at gemme tid i PostgreSQL ved hjælp af Java?

Enhver strategi til lagring af dato-og-tidsdata i PostgreSQL bør, IMO, stole på disse to punkter:

  • Din løsning bør aldrig afhænger af serverens eller klientens tidszoneindstilling.
  • I øjeblikket har PostgreSQL (som de fleste databaser) ikke en datatype til at gemme en fuld dato-og-klokkeslæt med tidszone. Så du skal vælge mellem en Instant eller en LocalDateTime datatype.

Min opskrift følger.

Hvis du vil optage det fysiske øjeblik når en bestemt begivenhed fandt sted (et ægte "tidsstempel " , typisk en eller anden oprettelse/ændring/sletningshændelse), brug derefter:

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

(Lad ikke PostgreSQL ejendommelige datatyper WITH TIMEZONE /WITHOUT TIMEZONE forvirre dig:ingen af ​​dem gemmer faktisk en tidszone)

Noget kedelkode:det følgende antager, at ps er en PreparedStatement , rs et ResultSet og tzUTC er en statisk Calendar objekt svarende til UTC tidszone.

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

Skriv Instant til databasen TIMESTAMPTZ :

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

Læs Instant fra databasen TIMESTAMPTZ :

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

Dette fungerer sikkert, hvis din PG-type er TIMESTAMPTZ (I så fald er calendarUTC har ingen effekt i den kode; men det er altid tilrådeligt ikke at være afhængig af standardtidszoner). "Sikkert" betyder, at resultatet ikke vil afhænge af server- eller databasetidszone , eller tidszoneoplysninger:handlingen er fuldt reversibel, og uanset hvad der sker med tidszoneindstillinger, vil du altid få det samme "øjeblikkelige tid", som du oprindeligt havde på Java-siden.

Hvis du i stedet for et tidsstempel (et øjeblik på den fysiske tidslinje) har at gøre med en "civil" lokal dato-tid (det vil sige sættet af felter {year-month-day hour:min:sec(:msecs)} ), skal du bruge:

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

Læs LocalDateTime fra databasen TIMESTAMP :

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

Skriv LocalDateTime til databasen TIMESTAMP :

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

Igen, denne strategi er sikker, og du kan sove roligt:​​hvis du har gemt 2011-10-30 23:59:30 , vil du hente disse præcise felter (time=23, minut=59... osv.) altid, uanset hvad - selvom tidszonen for din Postgresql-server (eller klient) i morgen ændres, eller din JVM eller dit OS-tidszone, eller hvis dit land ændrer sine sommertidsregler osv.

Tilføjet:Hvis du ønsker (det virker som et naturligt krav) at gemme den fulde datetime-specifikation (en ZonedDatetime :tidsstemplet sammen med tidszonen, som implicit også inkluderer den fulde civile datetime info - plus tidszonen)... så har jeg dårlige nyheder til dig:PostgreSQL har ikke en datatype for dette (hverken andre databaser, så vidt jeg ved) . Du skal udtænke dit eget lager, måske i et par felter:kunne være de to ovennævnte typer (meget overflødige, men effektive til hentning og beregning), eller en af ​​dem plus tidsforskydningen (du mister tidszoneinformationen, nogle beregninger bliver vanskelige, og nogle umulige), eller en af ​​dem plus tidszonen (som streng; nogle beregninger kan være ekstremt dyre).



  1. MySQL-installation:FEJL:Kunne ikke bygge gem native-udvidelse

  2. Hvad er forskellen mellem varchar og varchar2 i Oracle?

  3. Sådan øges den tilladte vedhæftede filstørrelse, når du sender e-mail i SQL Server (T-SQL)

  4. Er vi klar til Nordic PGDay?