2012-08-27 47 views
5

Tôi đang cố gắng thiết lập trường HOUR_OF_DAY và thay đổi Múi giờ của đối tượng ngày GregorianCalendar.Java GregorianCalendar thay đổi TimeZone

GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT+10")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 
date.set(Calendar.HOUR_OF_DAY, 23); 
//date.get(Calendar.HOUR_OF_DAY); 
date.setTimeZone(TimeZone.getTimeZone("GMT")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 

Output:

HOUR: 16 
HOUR: 23 

Đối với một số giá trị nguyên nhân của HOUR_OF_DAY không thay đổi sau khi cài đặt múi giờ khác nhau. Nhưng nếu tôi bỏ ghi chú date.get cho HOUR_OF_DAY, mọi thứ hoạt động chính xác như nó nên

GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT+10")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 
date.set(Calendar.HOUR_OF_DAY, 23); 
date.get(Calendar.HOUR_OF_DAY); // uncommenting this line will is changing the output 
date.setTimeZone(TimeZone.getTimeZone("GMT")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 

Output:

HOUR: 16 
HOUR: 13 

Làm thế nào có thể như vậy? Tại sao .get phương pháp đang thay đổi hành vi đối tượng?

Trả lời

8

Lớp GregorianCalendar kế thừa phương pháp của nó get từ Calendar, trong đó có các tác dụng phụ sau đây:

Trong chế độ khoan dung, tất cả các lĩnh vực lịch được chuẩn hóa.

Điều này có nghĩa rằng giá trị time và tất cả các lĩnh vực được tính lại khi get được gọi trên đối tượng Calendar. Điều này có thể dẫn đến một số hành vi không thể đoán trước, đặc biệt là khi kết hợp với setTimeZone, trong đó có một số documented buggy behavior của riêng nó.

0

tl; dr

OffsetDateTime.now(ZoneOffset.ofHours(10) ).withHour(23) 

Tránh thừa lớp ngày thời gian

Di sản các lớp học ngày thời gian bao gồm GregorianCalendar là một khó hiểu. rắc rối, thiết kế kém lộn xộn. Tránh chúng. Bây giờ được thay thế bởi các lớp học java.time. Cụ thể, GregorianCalendar được thay thế bằng ZonedDateTime.

offset-từ-UTC

Bạn dường như muốn có một khoảnh khắc với một offset-from-UTC của mười giờ trước UTC. Xác định bù đắp mong muốn của bạn.

ZoneOffset offset = ZoneOffset.ofHours(10) ; 

offset.toString(): 10: 00

Lấy thời điểm hiện tại như một OffsetDateTime với điều đó bù đắp.

OffsetDateTime odt = OffsetDateTime.now(offset) ; 

odt.toString(): 2018-02-15T16: 44: 44,216642 + 10: 00

Bạn muốn ghi đè giờ là 23.

OffsetDateTime odt23 = odt.withHour(23) ; 

odt23.toString(): 2018-02-15T23: 44: 44.216.642 + 10: 00

Múi giờ

Tôi đang cố gắng để thiết lập lĩnh vực HOUR_OF_DAY và thay đổi múi giờ của đối tượng ngày GregorianCalendar.

Không, bạn đang thay đổi offset-from-UTC, không phải là time zone.

Luôn sử dụng múi giờ tốt hơn là chỉ bù trừ, nếu bạn biết chắc chắn khu vực dự định. Múi giờ là lịch sử của những thay đổi trong quá khứ, hiện tại và tương lai đối với chênh lệch được sử dụng bởi những người ở một khu vực nhất định. Với múi giờ, bạn luôn có thể xác định độ lệch, nhưng không phải ngược lại.

Chỉ định proper time zone name trong định dạng của continent/region, chẳng hạn như America/Montreal, Africa/Casablanca, hoặc Pacific/Auckland. Không bao giờ sử dụng từ viết tắt 3-4 ký tự như EST hoặc IST vì chúng là không múi giờ thực, không được chuẩn hóa và thậm chí không độc đáo (!).

ZoneId z = ZoneId.of("Australia/Brisbane") ; 

Ghi lại khoảnh khắc hiện tại trong đồng hồ treo tường nhìn thấy bởi những người trong khu vực đó.

ZonedDateTime zdt = ZonedDateTime.now(z) ; 

Ghi đè giờ trong ngày.

ZonedDateTime zdt23 = zdt.withHour(23) ; 

Về java.time

Khung java.time được xây dựng vào Java 8 và sau đó. Các lớp này thay thế các lớp học ngày giờ legacy phiền hà cũ như java.util.Date, Calendar, & SimpleDateFormat.

Dự án Joda-Time, hiện đang ở maintenance mode, khuyên di chuyển đến các lớp java.time.

Để tìm hiểu thêm, hãy xem Oracle Tutorial. Và tìm kiếm Stack Overflow cho nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310.

Sử dụng JDBC driver tương thích với JDBC 4.2 hoặc cao hơn, bạn có thể trao đổi java.time đối tượng trực tiếp với cơ sở dữ liệu của bạn. Không cần chuỗi và các lớp java.sql. *.

Nơi lấy các lớp java.time?

  • Java SE 8, Java SE 9, và sau đó
    • Built-in.
    • Một phần của API Java chuẩn với gói được triển khai.
    • Java 9 thêm một số tính năng và bản sửa lỗi nhỏ.
  • Java SE 6Java SE 7
    • Hầu hết các chức năng java.time được back-chuyển đến Java 6 & 7 trong ThreeTen-Backport.
  • Android
    • phiên bản sau của triển khai bó Android của các lớp java.time.
    • Đối với Android trước đó, dự án ThreeTenABP thích hợp ThreeTen-Backport (đã đề cập ở trên). Xem How to use ThreeTenABP….

Dự án mở rộng ThreeTen-Extra java.time với các lớp bổ sung. Dự án này là một nền tảng chứng minh cho những bổ sung có thể có trong tương lai vào java.time. Bạn có thể tìm thấy một số lớp học hữu ích tại đây như Interval, YearWeek, YearQuartermore.

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