2015-09-29 18 views
9

Tôi đang nghĩ đến việc sử dụng java 8 Date Time API mới. Tôi googled một chút và tìm thấy jodaTime như là sự lựa chọn tốt cho java nhưng vẫn loại quan tâm để xem làm thế nào API mới này hoạt động.API Java Date Time mới của Java 8 có xử lý DST không?

Tôi đang lưu trữ tất cả thời gian trong giá trị UTC trong kho dữ liệu của mình và sẽ chuyển đổi chúng sang giá trị cụ thể theo múi giờ địa phương dựa trên múi giờ của người dùng. Tôi có thể tìm thấy nhiều bài viết cho thấy cách sử dụng API thời gian ngày Java mới. Tuy nhiên, tôi không chắc liệu API sẽ quản lý các thay đổi của DST? Hay chúng ta có cách xử lý ngày tốt hơn?

Tôi chỉ đang học API ngày mới, vì vậy hãy nghĩ đến việc nghe suy nghĩ của bạn về việc xử lý DateTime và hiển thị nó trên cơ sở Người dùng TimeZone.

+3

Tóm lại: có, DST được thực hiện. API ngày 8 của Java được tạo dựa trên thời gian Joda. –

+1

@Raja Tôi sẽ sửa các điều khoản của bạn để tránh nhầm lẫn ... "Địa phương" trong công việc ban ngày có nghĩa là "cho bất kỳ địa phương nào", như trong "Giáng sinh bắt đầu lúc nửa đêm ngày 25 tháng 12 năm 2015". Ngày giờ địa phương như vậy không có múi giờ. Thật vậy, nó không có ý nghĩa thực sự cho đến khi bạn điều chỉnh nó thành một múi giờ cụ thể. Nửa đêm ngày 25 đến sớm hơn ở Paris hơn là ở Montréal. Vì vậy, trong các ứng dụng kinh doanh phổ biến, chúng tôi hiếm khi sử dụng "Địa phương". Bạn sẽ lấy các giá trị ngày giờ được lưu trữ của bạn từ cơ sở dữ liệu của bạn, làm việc với chúng trong logic nghiệp vụ của bạn trong UTC nói chung, và chỉ điều chỉnh thành 'ZonedDateTime' để trình bày cho người dùng. –

Trả lời

15

Nó phụ thuộc vào lớp y sử dụng:

  • Instant là điểm tức thời trên dòng thời gian toàn cầu (UTC) và không liên quan đến múi giờ.
  • LocalDateLocalDateTime không có khái niệm múi giờ, nhưng gọi số now() tất nhiên sẽ cung cấp cho bạn thời gian chính xác của bạn.
  • OffsetDateTime có múi giờ, nhưng không hỗ trợ Thời gian tiết kiệm ánh sáng ban ngày.
  • ZonedDateTime có hỗ trợ múi giờ đầy đủ.

Chuyển đổi giữa chúng thường đòi hỏi một múi giờ, vì vậy để trả lời câu hỏi của bạn:

        Vâng, Java 8 Ngày/Giờ thể chăm sóc DST, nếu bạn sử dụng đúng.

+0

cảm ơn vì đã đề cập rằng 'OffsetDateTime' không hỗ trợ DST, đó chính xác là những gì tôi cần, cảm ơn! –

3

Có, API Java sẽ tính đến các thay đổi DST.

Hướng dẫn này giải thích khá tốt như thế nào để chuyển đổi số ngày giữa các múi giờ và làm thế nào để lựa chọn lớp quyền đại diện cho một ngày: https://docs.oracle.com/javase/tutorial/datetime/iso/timezones.html

Bạn cũng có thể nhìn vào lớp học này đại diện cho các quy tắc cho từng khu vực: http://docs.oracle.com/javase/8/docs/api/java/time/zone/ZoneRules.html

Đặc biệt, phương pháp này có thể cho bạn biết nếu một khoảnh khắc đặc biệt là tiết kiệm ánh sáng ban ngày: http://docs.oracle.com/javase/8/docs/api/java/time/zone/ZoneRules.html#isDaylightSavings-java.time.Instant-

+0

Cảm ơn bạn đã nhắc nhở giá trị của tài liệu Orcale :) Các liên kết này hữu ích hơn cho tôi. – Raja

14

The Answer bởi Andreas được phát hiện chính xác.

Mã ví dụ

Hãy kiểm tra bằng một số mã. DST in the United States & Canada hết hạn trong năm nay lúc 02:00 ngày 1 tháng 11 năm 2015.

Hãy bắt đầu với 1 giờ sáng theo giờ địa phương, có nghĩa là không được gắn với dòng thời gian và bỏ qua vấn đề múi giờ. Thêm một giờ và chúng tôi nhận được 2 giờ sáng. Có ý nghĩa.

LocalDateTime localDateTime = LocalDateTime.of(2015 , Month.NOVEMBER , 1 , 1 , 0); // 1 AM anywhere. Not tied the timeline nor to any time zone. 
LocalDateTime localDateTimeOneHourLater = localDateTime.plusHours(1); // 2 AM anywhere, in no particular time zone, ignoring DST. 

Tiếp theo chúng tôi nhận cụ thể, với múi giờ cụ thể.Chúng tôi lấy 1 AM bất cứ nơi nào và đặt nó vào múi giờ America/Los_Angeles (bờ biển phía tây của Hoa Kỳ).

ZoneId zoneId_LosAngeles = ZoneId.of("America/Los_Angeles"); 
ZonedDateTime before = localDateTime.atZone(zoneId_LosAngeles); // Assign a time zone, tying this vague date-time idea/generality to an actual moment on the time line. 

Bây giờ thêm giờ và xem những gì chúng tôi nhận được. Nếu DST bị bỏ qua, chúng tôi sẽ nhận được 2 giờ sáng. Nếu DST được tôn trọng, chúng tôi sẽ nhận được 1 AM… khi đạt đến 2 AM, wall-clock time sẽ chuyển về 1 AM nhưng với khoản bù trừ mới từ UTC. Đây là thông tục được gọi là "fall back" vào mùa thu (mùa thu).

ZonedDateTime after = before.plusHours(1); // 2 AM? Nope, 1 AM because DST Daylight Saving Time expires at 2 AM Nov 1, 2015. 

Dump to console.

System.out.println("localDateTime : " + localDateTime); 
System.out.println("localDateTimeOneHourLater : " + localDateTimeOneHourLater); 
System.out.println("before : " + before); 
System.out.println("after : " + after); 

Khi chạy, chúng tôi nhận được kết quả này. Không có múi giờ, 1 giờ sáng + 1 giờ = 2 giờ sáng. Hãy nhớ rằng đây là các giá trị ngày giờ "địa phương", không phải là UTC. Chúng chỉ đại diện cho ý tưởng mơ hồ về thời gian ngày, không phải là thời điểm thực tế trên dòng thời gian.

localDateTime : 2015-11-01T01:00 
localDateTimeOneHourLater : 2015-11-01T02:00 

Nhưng với múi giờ được áp dụng vào ngày DST hết hạn, chúng tôi nhận được kết quả khác nhau. Lưu ý cách thời gian trong ngày vẫn là 01:00 nhưng thay đổi offset-from-UTC từ -07:00 đến -08:00.

before : 2015-11-01T01:00-07:00[America/Los_Angeles] 
after : 2015-11-01T01:00-08:00[America/Los_Angeles] 

Có lẽ điều này sẽ rõ ràng và dễ dàng hơn để xác minh xem chúng tôi có điều chỉnh thành UTC hay không. Chúng ta có thể làm điều đó đơn giản bằng cách truy cập các đối tượng beforeafter như đối tượng Instant. System.out.println sau đó ngầm gọi phương thức toString.

System.out.println("before.toInstant : " + before.toInstant()); 
System.out.println("after.toInstant : " + after.toInstant()); 

Khi chạy.

before.toInstant : 2015-11-01T08:00:00Z 
after.toInstant : 2015-11-01T09:00:00Z 
Các vấn đề liên quan