Các Oracle Hướng dẫn là không chính xác
Thật không may, Hướng dẫn Oracle không chính xác về vấn đề này. Dòng mã ví dụ đó đơn giản là sai. Bạn nắm bắt tốt.
Lỗi này khá đáng tiếc vì Hướng dẫn này là một nguồn tốt để học và nghiên cứu Java.
Instant::plus
Các Instant
lớp học không có phương pháp như plusHours
quy định tại một trong hai Java 8 hoặc Java 9.
Thay vào đó, bạn có thể gọi plus
phương thức và chỉ định giờ.
Instant later = instant.plus( 1 , ChronoUnit.HOURS ) ;
ZonedDateTime::plusHours
Các Instant
lớp là một lớp xây dựng khối cơ bản, chỉ một khoảnh khắc trên Timeline trong UTC . Thông thường, khi thực hiện các thao tác như thêm giờ, bạn có thể muốn tính đến các yếu tố bất thường chẳng hạn như Giờ tiết kiệm ánh sáng ban ngày và vì vậy bạn sẽ quan tâm đến múi giờ . Đối với điều đó, hãy sử dụng ZonedDateTime
lớp học. Lớp đó cung cấp một plusHours
phương pháp thuận tiện , có thể là nguồn gây nhầm lẫn cho các tác giả Hướng dẫn .
Chỉ định một tên múi giờ thích hợp trong các đị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 chữ cái, chẳng hạn như EST
hoặc IST
vì chúng không phải là múi giờ thực, không được tiêu chuẩn hóa và thậm chí không phải là duy nhất (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
ZonedDateTime zdtLater = zdt.plusHours( 1 ) ;
Instant
đấu với ZonedDateTime
Hãy xem một ví dụ về sự bất thường trong việc thêm giờ. Khi khoanh vùng, chúng tôi thêm một giờ vào thời điểm cụ thể là 1 giờ sáng ngày 23 tháng 3 năm 2017 và tất nhiên là dự kiến 2 giờ sáng, nhưng chúng tôi rất ngạc nhiên khi thấy 3 giờ sáng. Tuy nhiên, khi chúng tôi xem xét cùng một thời điểm ở UTC chứ không phải múi giờ cụ thể đó, cùng một điểm trên dòng thời gian, thêm một giờ hoạt động như mong đợi.
Sự bất thường đặc biệt này là do việc áp dụng Giờ tiết kiệm ánh sáng ban ngày (DST) ở hầu hết Bắc Mỹ, cụ thể là ở đây, múi giờ America/New_York
. Vào mùa xuân, đồng hồ "chuyển tiếp" một giờ. Khi đồng hồ điểm 2 giờ sáng, chúng chuyển sang 3 giờ sáng. Vì vậy, giờ hai giờ không bao giờ tồn tại trong ngày đó.
LocalDate ld = LocalDate.of( 2017 , Month.MARCH , 12 ) ;
LocalTime lt = LocalTime.of( 1 , 0 ) ;
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
ZonedDateTime zdtOneHourLater = zdt.plusHours( 1 ) ;
System.out.println( "zdt: " + zdt ) ;
System.out.println( "zdtOneHourLater: " + zdtOneHourLater ) ;
System.out.println( "Yikes! 1 AM plus an hour is 3 AM? Yes, that is an anomaly known as Daylight Saving Time (DST)." ) ;
System.out.println( "" ) ;
Instant instant = zdt.toInstant() ;
Instant instantOneHourLater = instant.plus( 1 , ChronoUnit.HOURS ) ;
System.out.println( "instant: " + instant ) ;
System.out.println( "instantOneHourLater: " + instantOneHourLater ) ;
System.out.println( "Instant is always in UTC. So no anomalies, no DST. Adding an hour to 1 AM results in 2 AM every time." ) ;
Xem mã này chạy trực tiếp tại IdeOne.com .
zdt: 2017-03-12T01: 00-05: 00 [Châu Mỹ / New_York]
zdtOneHourLater: 2017-03-12T03: 00-04: 00 [Mỹ / New_York]
Rất tiếc! 1 giờ sáng cộng với một giờ là 3 giờ sáng? Vâng, đó là một điều bất thường được gọi là Giờ tiết kiệm ánh sáng ban ngày (DST).
tức thì: 2017-03-12T06: 00: 00Z
InstantOneHourLater: 2017-03-12T07: 00: 00Z
Instant luôn ở UTC. Vì vậy, không có dị thường, không có DST. Thêm một giờ đến 1 giờ sáng, kết quả là 2 giờ sáng mọi lúc.