sql >> Databasteknik >  >> RDS >> PostgreSQL

Vilket är det mest rekommenderade sättet att lagra tid i PostgreSQL med Java?

Alla strategier för att lagra datum- och tiddata i PostgreSQL bör, IMO, förlita sig på dessa två punkter:

  • Din lösning bör aldrig beror på serverns eller klientens tidszonsinställning.
  • För närvarande har PostgreSQL (som de flesta databaser) ingen datatyp för att lagra en full datum och tid med tidszon. Så du måste välja mellan en Instant eller en LocalDateTime datatyp.

Mitt recept följer.

Om du vill spela in det fysiska ögonblicket när en viss händelse inträffade (en sann "tidsstämpel " , vanligtvis någon skapande/ändring/borttagningshändelse), använd sedan:

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

(Låt inte PostgreSQL märkliga datatyper WITH TIMEZONE /WITHOUT TIMEZONE förvirra dig:ingen av dem lagrar faktiskt en tidszon)

Någon typkod:följande antar att ps är en PreparedStatement , rs en ResultSet och tzUTC är en statisk Calendar objekt som motsvarar UTC tidszon.

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

Skriv Instant till databasen TIMESTAMPTZ :

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

Läs Instant från databasen TIMESTAMPTZ :

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

Detta fungerar säkert om din PG-typ är TIMESTAMPTZ (I så fall, calendarUTC har ingen effekt i den koden; men det är alltid tillrådligt att inte vara beroende av standardtidszoner). "Säkert" betyder att resultatet inte beror på serverns eller databasens tidszon , eller tidszonsinformation:operationen är helt reversibel, och vad som än händer med tidszonsinställningarna kommer du alltid att få samma "instant of time" som du ursprungligen hade på Java-sidan.

Om du istället för en tidsstämpel (ett ögonblick på den fysiska tidslinjen) har att göra med en "civil" lokal datum-tid (det vill säga uppsättningen fält {year-month-day hour:min:sec(:msecs)} ), skulle du använda:

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

Läs LocalDateTime från 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 till databasen TIMESTAMP :

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

Återigen, den här strategin är säker och du kan sova lugnt:om du lagrade 2011-10-30 23:59:30 , du kommer att hämta de exakta fälten (timme=23, minut=59... etc) alltid, oavsett vad - även om tidszonen för din Postgresql-server (eller klient) ändras i morgon, eller din JVM eller ditt OS-tidszon, eller om ditt land ändrar sina sommartidsregler etc.

Tillagd:Om du vill (det verkar vara ett naturligt krav) lagra den fullständiga datetime-specifikationen (en ZonedDatetime :tidsstämpeln tillsammans med tidszonen, som implicit också inkluderar den fullständiga civila datetime info - plus tidszonen)... så har jag dåliga nyheter till dig:PostgreSQL har ingen datatyp för detta (inte heller andra databaser, såvitt jag vet) . Du måste skapa din egen lagring, kanske i ett par fält:kan vara de två ovanstående typerna (mycket redundant, men effektiv för hämtning och beräkning), eller en av dem plus tidsförskjutningen (du tappar tidszonsinformationen, vissa beräkningar blir svårt, och vissa omöjligt), eller en av dem plus tidszonen (som sträng; vissa beräkningar kan vara extremt kostsamma).



  1. Hur man löser ORA-06512 på radnummer

  2. LINQ till SQL Take w/o Skip Orsakar flera SQL-satser

  3. Hur kan jag använda förberedda uttalanden i CodeIgniter

  4. SQL Server ROUND()-funktion:Vad det är till för och varför ska du bry dig?