PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Apa cara yang paling direkomendasikan untuk menyimpan waktu di PostgreSQL menggunakan Java?

Strategi apa pun untuk menyimpan data tanggal dan waktu di PostgreSQL harus, IMO, bergantung pada dua poin ini:

  • Solusi Anda seharusnya tidak pernah bergantung pada pengaturan zona waktu server atau klien.
  • Saat ini, PostgreSQL (seperti kebanyakan database) tidak memiliki tipe data untuk menyimpan penuh tanggal-dan-waktu dengan zona waktu. Jadi, Anda perlu memutuskan antara Instant atau LocalDateTime tipe data.

Resep saya berikut.

Jika Anda ingin merekam fisik instan pada saat peristiwa tertentu terjadi, ("stempel waktu . yang sebenarnya " , biasanya beberapa peristiwa pembuatan/modifikasi/penghapusan), lalu gunakan:

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

(Jangan biarkan PostgreSQL tipe data aneh WITH TIMEZONE /WITHOUT TIMEZONE membingungkan Anda:tidak ada yang benar-benar menyimpan zona waktu)

Beberapa kode boilerplate:berikut ini mengasumsikan bahwa ps adalah PreparedStatement , rs sebuah ResultSet dan tzUTC adalah Calendar statis objek yang sesuai dengan UTC zona waktu.

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

Tulis Instant ke database TIMESTAMPTZ :

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

Baca Instant dari basis data TIMESTAMPTZ :

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

Ini bekerja dengan aman jika tipe PG Anda adalah TIMESTAMPTZ (Dalam hal ini, calendarUTC tidak berpengaruh dalam kode itu; tetapi selalu disarankan untuk tidak bergantung pada zona waktu default).."Aman" berarti bahwa hasilnya tidak bergantung pada zona waktu server atau basis data , atau informasi zona waktu:operasi ini sepenuhnya dapat dibalik, dan apa pun yang terjadi pada pengaturan zona waktu, Anda akan selalu mendapatkan "waktu instan" yang sama dengan yang Anda miliki di sisi Java.

Jika, alih-alih stempel waktu (seketika pada garis waktu fisik), Anda berurusan dengan waktu-tanggal lokal "sipil" (yaitu, kumpulan bidang {year-month-day hour:min:sec(:msecs)} ), Anda akan menggunakan:

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

Baca LocalDateTime dari basis data TIMESTAMP :

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

Tulis LocalDateTime ke database TIMESTAMP :

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

Sekali lagi, strategi ini aman dan Anda dapat tidur nyenyak:jika Anda menyimpan 2011-10-30 23:59:30 , Anda akan selalu mengambil bidang yang tepat tersebut (jam=23, menit=59... dll) selalu, apa pun yang terjadi - bahkan jika besok zona waktu server Postgresql (atau klien) Anda berubah, atau JVM atau zona waktu OS Anda, atau jika negara Anda mengubah aturan DST-nya, dll.

Ditambahkan:Jika Anda ingin (tampaknya merupakan persyaratan alami) untuk menyimpan spesifikasi datetime lengkap (ZonedDatetime :stempel waktu bersama dengan zona waktu, yang secara implisit juga mencakup info tanggal waktu sipil lengkap - ditambah zona waktu)... . Anda harus merancang penyimpanan Anda sendiri, mungkin dalam sepasang bidang:bisa dua jenis di atas (sangat berlebihan, meskipun efisien untuk pengambilan dan perhitungan), atau salah satunya ditambah offset waktu (Anda kehilangan info zona waktu, beberapa perhitungan menjadi sulit, dan beberapa tidak mungkin), atau salah satunya ditambah zona waktu (sebagai string; beberapa perhitungan bisa sangat mahal).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dapatkan waktu eksekusi kueri PostgreSQL

  2. SQL di mana set yang digabungkan harus berisi semua nilai tetapi mungkin berisi lebih banyak

  3. Cara Mendefinisikan Kunci Utama Peningkatan Otomatis di PostgreSQL

  4. Cara Menyebarkan PostgreSQL untuk Ketersediaan Tinggi

  5. Fitur PostgreSQL Enterprise Baru dan Berkembang dengan Rilis Terbaru