2011-09-30 38 views
21

Mysql chạy lúc GMT + 8 nhưng tomcat chạy lúc GMT. khi lưu datetime vào cơ sở dữ liệu, dường như chạy ok, khi tôi kiểm tra giá trị datetime trong DB, tôi thấy giá trị GMT. Nhưng khi tôi cố gắng lấy giá trị từ DB, giá trị được thay đổi, dường như giá trị trong DB được lấy như GMT + 8, vì vậy java thay đổi giá trị thành GMT.Cách thay đổi múi giờ mysql trong kết nối java

tôi cố gắng thiết lập các kết nối url thêm

useTimezone=true&serverTimezone=GMT 

nhưng không hoạt động

+0

Bạn chỉ nhận được múi giờ "sai" hoặc giá trị có sai không? – Thilo

+0

Tôi thay đổi cấu hình để sử dụngGmtMillisForDatetimes = true & serverTimezone = GMT. có vẻ đó là hành vi tôi muốn. nhưng vẫn còn bối rối. – Xilang

Trả lời

47

useTimezone là một workaround cũ. Nhóm MySQL viết lại mã setTimestamp/getTimestamp khá gần đây, nhưng nó sẽ chỉ được kích hoạt nếu bạn đặt tham số kết nối useLegacyDatetimeCode = false và bạn đang sử dụng phiên bản mới nhất của trình kết nối JDBC mysql. Vì vậy, ví dụ:

String url = 
"jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false 

Nếu bạn tải về mã nguồn mysql-connector và nhìn vào setTimestamp, nó rất dễ dàng để xem những gì đang xảy ra:

Nếu việc sử dụng di sản ngày mã thời gian = false, newSetTimestampInternal (.. .) được gọi là. Sau đó, nếu Lịch truyền cho newSetTimestampInternal là NULL, đối tượng ngày bạn được định dạng theo múi giờ của cơ sở dữ liệu:

this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US); 
this.tsdf.setTimeZone(this.connection.getServerTimezoneTZ()); 
timestampString = this.tsdf.format(x); 

Nó rất quan trọng là Lịch là null - do đó hãy chắc chắn rằng bạn đang sử dụng:

setTimestamp(int,Timestamp). 

... NOT setTimestamp (int, Dấu thời gian, Lịch).

Điều hiển nhiên là cách thức hoạt động của tính năng này. Nếu bạn xây dựng một ngày: 5 tháng 1, 2011 3:00 sáng tại Mỹ/Los_Angeles (hoặc bất kỳ múi giờ nào bạn muốn) bằng cách sử dụng java.util.Calendar và gọi setTimestamp (1, myDate), thì nó sẽ lấy ngày của bạn, sử dụng SimpleDateFormat định dạng nó trong múi giờ cơ sở dữ liệu . Vì vậy, nếu DB của bạn là ở Mỹ/New_York, nó sẽ xây dựng chuỗi '2011-01-05 6:00:00' để được chèn (kể từ NY đến trước LA 3 giờ).

Để truy xuất ngày, hãy sử dụng getTimestamp (int) (không có Lịch). Một lần nữa nó sẽ sử dụng múi giờ cơ sở dữ liệu để xây dựng một ngày.

Lưu ý: Múi giờ của máy chủ web hoàn toàn không liên quan ngay bây giờ! Nếu bạn không đặt useLegacyDatetimecode thành false, múi giờ máy chủ web được sử dụng để định dạng - thêm nhiều nhầm lẫn.


Lưu ý:

Có thể MySQL của tôi phàn nàn rằng múi giờ máy chủ là mơ hồ. Ví dụ, nếu cơ sở dữ liệu của bạn được thiết lập để sử dụng EST, có thể có nhiều múi giờ EST thể trong Java, vì vậy bạn có thể làm rõ điều này cho mysql-connector bằng cách nói nó chính xác những gì múi giờ cơ sở dữ liệu là:

String url = 
"jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false&serverTimezone=America/New_York"; 

Bạn chỉ cần làm điều này nếu nó than phiền.

+0

Cảm ơn bạn đã sử dụngLegacyDatetimeChú ý mã nguồn!Lưu ý: Điều này cũng giải quyết được vấn đề của tôi khi làm việc với Joda Time (thông qua add-on heapnate usertypes). – Pete

+0

Vì vậy, với serverTimezone và useLegacyDatetimeCode được thêm vào chuỗi kết nối của tôi, tôi có thể gửi một Timestmp và nó được ghi lại chính xác trong cột DateTime vì đó là thời gian UTC. Tôi có thể thấy nó trên bảng điều khiển MySQL của tôi như vậy. Khi tôi thực hiện lệnh SELECT qua JDBC và cố gắng lấy dữ liệu ra, nó vẫn tự động chuyển đổi nó trong lớp JDBC. Tôi đã thử getObject() và geTimestmp (cả hai không có và với một đối tượng lịch UTC) và nó tiếp tục quay trở lại trong thời gian cục bộ. – djsumdog

+0

Hóa ra đây là cài đặt tôi cần để giải quyết vấn đề sản xuất. Tại địa phương chúng tôi không thể tái tạo nó. Nhưng cố gắng này trong trình điều khiển về sản xuất loại bỏ các gian hàng chúng tôi đã thấy sau 10-30 giây của chế biến. –

Các vấn đề liên quan