PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Cách được khuyến nghị nhất để lưu trữ thời gian trong PostgreSQL bằng Java là gì?

Bất kỳ chiến lược nào để lưu trữ dữ liệu ngày và giờ trong PostgreSQL, IMO, nên dựa trên hai điểm sau:

  • Giải pháp của bạn nên không bao giờ phụ thuộc vào cài đặt múi giờ của máy chủ hoặc máy khách.
  • Hiện tại, PostgreSQL (như hầu hết các cơ sở dữ liệu) không có kiểu dữ liệu để lưu trữ đầy đủ ngày và giờ với múi giờ. Vì vậy, bạn cần phải quyết định giữa Instant hoặc LocalDateTime kiểu dữ liệu.

Công thức của tôi sau đây.

Nếu bạn muốn ghi lại tức thì vật lý tại thời điểm một sự kiện cụ thể xảy ra, (một " dấu thời gian đúng ", thường là một số sự kiện tạo / sửa đổi / xóa), sau đó sử dụng:

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

(Đừng để các kiểu dữ liệu đặc biệt của PostgreSQL WITH TIMEZONE / WITHOUT TIMEZONE làm bạn bối rối:không ai trong số họ thực sự lưu trữ múi giờ)

Một số đoạn mã soạn sẵn:đoạn mã sau giả định rằng ps là một PreparedStatement , rs a ResultSettzUTC là một Calendar tĩnh đối tượng tương ứng với UTC múi giờ.

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

Viết Instant vào cơ sở dữ liệu TIMESTAMPTZ :

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

Đọc Instant từ cơ sở dữ liệu TIMESTAMPTZ :

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

Điều này hoạt động an toàn nếu loại PG của bạn là TIMESTAMPTZ (Trong trường hợp đó, calendarUTC không có hiệu lực trong mã đó; nhưng không nên phụ thuộc vào múi giờ mặc định). "An toàn" có nghĩa là kết quả sẽ không phụ thuộc vào múi giờ của máy chủ hoặc cơ sở dữ liệu hoặc thông tin múi giờ:thao tác này hoàn toàn có thể đảo ngược và bất kỳ điều gì xảy ra với cài đặt múi giờ, bạn sẽ luôn nhận được cùng một "khoảnh khắc thời gian" mà bạn đã có ở bên Java.

Nếu, thay vì dấu thời gian (tức thì trên dòng thời gian thực), bạn đang xử lý ngày giờ địa phương "dân sự" (nghĩa là, tập hợp các trường {year-month-day hour:min:sec(:msecs)} ), bạn sẽ sử dụng:

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

Đọc LocalDateTime từ cơ sở dữ liệu TIMESTAMP :

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

Viết LocalDateTime tới cơ sở dữ liệu TIMESTAMP :

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

Một lần nữa, chiến lược này an toàn và bạn có thể ngủ yên:nếu bạn đã lưu trữ 2011-10-30 23:59:30 , bạn sẽ luôn truy xuất các trường chính xác đó (giờ =23, phút =59 ... v.v.), bất kể điều gì - ngay cả khi ngày mai múi giờ của máy chủ Postgresql (hoặc máy khách) của bạn thay đổi, hoặc JVM hoặc múi giờ hệ điều hành của bạn, hoặc nếu quốc gia của bạn sửa đổi các quy tắc DST, v.v.

Đã thêm:Nếu bạn muốn (có vẻ như là một yêu cầu tự nhiên) để lưu trữ thông số ngày giờ đầy đủ (một ZonedDatetime :dấu thời gian cùng với múi giờ, mặc nhiên cũng bao gồm thông tin ngày giờ dân sự đầy đủ - cộng với múi giờ) ... thì tôi có tin xấu cho bạn:PostgreSQL không có kiểu dữ liệu cho điều này (theo hiểu biết của tôi cũng không phải là cơ sở dữ liệu khác) . Bạn phải thiết lập bộ nhớ của riêng mình, có lẽ trong một cặp trường:có thể là hai loại trên (dư thừa cao, mặc dù hiệu quả cho việc truy xuất và tính toán) hoặc một trong số chúng cộng với khoảng thời gian (bạn mất thông tin múi giờ, một số tính toán trở thành khó và một số không thể thực hiện được) hoặc một trong số chúng cộng với múi giờ (dưới dạng chuỗi; một số phép tính có thể cực kỳ tốn kém).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sự hiểu biết về hoạt động hàng loạt của JDBC

  2. Truyền kiểu NULL khi cập nhật nhiều hàng

  3. Các tính năng PostgreSQL Enterprise mới và đang phát triển với các bản phát hành gần đây

  4. Cách tạo biểu đồ trong PostgreSQL

  5. Trừ các tuần cho một ngày trong PostgreSQL