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

Cài đặt Trình điều khiển JDBC-mysql để xử lý tốt DATETIME và TIMESTAMP trong UTC là gì?

Giải pháp là đặt tham số kết nối JDBC noDatetimeStringSync=true với useLegacyDatetimeCode=false . Như một phần thưởng, tôi cũng tìm thấy sessionVariables=time_zone='-00:00' giảm bớt sự cần thiết phải set time_zone rõ ràng trên mọi kết nối mới.

Có một số mã chuyển đổi múi giờ "thông minh" được kích hoạt sâu bên trong ResultSet.getString() khi phát hiện cột là TIMESTAMP cột.

Than ôi, mã thông minh này có một lỗi:TimeUtil.fastTimestampCreate(TimeZone tz, int year, int month, int day, int hour, int minute, int seconds, int secondsPart) trả về Timestamp được gắn thẻ sai vào múi giờ mặc định của JVM, ngay cả khi tz tham số được đặt thành một cái gì đó khác:

final static Timestamp fastTimestampCreate(TimeZone tz, int year, int month, int day, int hour, int minute, int seconds, int secondsPart) {
    Calendar cal = (tz == null) ? new GregorianCalendar() : new GregorianCalendar(tz);
    cal.clear();

    // why-oh-why is this different than java.util.date, in the year part, but it still keeps the silly '0' for the start month????
    cal.set(year, month - 1, day, hour, minute, seconds);

    long tsAsMillis = cal.getTimeInMillis();

    Timestamp ts = new Timestamp(tsAsMillis);
    ts.setNanos(secondsPart);

    return ts;
}

ts trả về sẽ hoàn toàn hợp lệ ngoại trừ khi tiếp tục lên trong chuỗi cuộc gọi, nó được chuyển đổi trở lại thành chuỗi bằng cách sử dụng toString() trần phương thức này hiển thị ts dưới dạng Chuỗi đại diện cho đồng hồ sẽ hiển thị trong múi giờ mặc định của JVM, thay vì chuỗi biểu thị thời gian theo UTC. Trong ResultSetImpl.getStringInternal(int columnIndex, boolean checkDateTypes) :

                case Types.TIMESTAMP:
                    Timestamp ts = getTimestampFromString(columnIndex, null, stringVal, this.getDefaultTimeZone(), false);

                    if (ts == null) {
                        this.wasNullFlag = true;

                        return null;
                    }

                    this.wasNullFlag = false;

                    return ts.toString();

Đặt noDatetimeStringSync=true vô hiệu hóa toàn bộ mớ hỗn độn phân tích cú pháp / hủy phân tích cú pháp và chỉ trả về giá trị chuỗi như-được nhận từ cơ sở dữ liệu.

Đầu ra thử nghiệm:

0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

useLegacyDatetimeCode=false vẫn quan trọng vì nó thay đổi hành vi của getDefaultTimeZone() để sử dụng TZ của máy chủ cơ sở dữ liệu.

Trong khi tìm kiếm điều này, tôi cũng tìm thấy tài liệu cho useJDBCCompliantTimezoneShift là không chính xác, mặc dù nó không có gì khác biệt:tài liệu cho biết [ Đây là một phần của mã ngày-giờ kế thừa, do đó thuộc tính chỉ có hiệu lực khi "useLegacyDatetimeCode =true". ], nhưng sai rồi, hãy xem ResultSetImpl.getNativeTimestampViaParseConversion(int, Calendar, TimeZone, boolean) .




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Riêng biệt phiên bản khác nhau của một trang web

  2. Tạo một trang web với MySQL

  3. Hàm GREATEST () MySQL - Tìm đối số lớn nhất trong danh sách đối số

  4. CHỌN tất cả các bản ghi 30 ngày tuổi

  5. Hiển thị dữ liệu từ MYSQL; Lỗi câu lệnh SQL