... LocalDateTime để tạo đối tượng ZonedDateTime cách gọi local.atZone(zoneId): ZonedDateTime dateTime = local.atZone(zoneId): o Bằng cách gọi phương thức static ZonedDateTime.of (year, month, day, hour,... dụ: ZonedDateTime apollo11launch = ZonedDateTime.of(1969, 7, 16, 9, 32, 4, 0, ZoneId.of("America/New_York")); 16T09:32-04:00[America/New_York] // 1969-07- o Tạo từ chuỗi: ZonedDateTime dateTime... lưu trữ ZonedDateTime - Tạo đối tượng ZonedDateTime: o Cho ID time zone, phương thức static ZoneId.of (id) trả đối tượng ZoneId Bạn sử dụng đối tượng ZoneId kết hợp với đối tượng LocalDateTime để
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG BÀI TẬP LỚN Môn lập trình Java Sinh viên thực hiện: Hoàng Văn Đông MSSV: 20124976 Giảng viên hướng dẫn: TS. Nguyễn Hồng Quang Hà Nội - 2015 Chương 5. The New Date and Time API 5.5 Múi giờ (Zoned Time) Phần 1 Lý thuyết 1. Các khái niệm: - Khi bạn thực hiện một ứng dụng lịch hay vấn ứng dụng nào nó liên quan đến thời gian thực tế, làm việc cho những người bay từ nước này sang nước khác. Cần phải thực hiện tính toán múi giờ hợp lý để đưa ra được thời gian đúng. Ví dụ, bạn đang ở Hà Nội lúc 8:00 và cần đến dự một hội nghị diễn ra ở Paris vào lúc 10 giờ, nhưng là giờ Paris, ứng dụng cần phải thông báo thời gian chính xác thời gian còn lại đến khi diễn ra hội nghị để người dùng biết và chuẩn bị. - Múi giờ (timezones): Theo wiki tiếng Việt một múi giờ là một vùng trên Trái Đất mà người ta quy ước sử dụng cùng một thời gian tiêu chuẩn, thông thường được nói đến như là giờ địa phương. Về lý thuyết, các đồng hồ tại vùng này luôn chỉ cùng một thời gian. - Tổ chức cấp phát số hiệu Internet (Internet Assigned Numbers Authority IANA) giữ một cơ sở dữ liệu của tất cả các múi giờ được biết đến trên toàn thế giới (https://www.iana.org/time-zones), được cập nhật nhiều lần trong năm và tự động cập nhật với các quy tắc thay đổi cho “giờ mùa hè” (daylight savings time – DST). Java sử dụng cơ sở dữ liệu IANA. Mỗi múi giờ có một ID, như: Mỹ / New_York hoặc Châu Âu / Berlin. Để tìm hiểu tất cả các múi giờ có sẵn, gọi ZoneId.getAvailableIds. Tại thời điểm viết sách này, đã có gần 600 ID. - Quy ước giờ mùa hè (daylight saving time - DST): o Là quy ước chỉnh đồng hồ tăng thêm một khoảng thời gian (thường là 1 giờ) so với giờ tiêu chuẩn, tại một số địa phương của một số quốc gia, trong một giai đoạn (thường là vào mùa hè) trong năm. o Quy ước này thường được thực hiện tại các nước ôn đới hay gần cực, nơi mà vào mùa hè, ban ngày bắt đầu sớm hơn so với mùa đông vài tiếng đồng hồ. Nó có ý nghĩa thực tiễn là giúp tiết kiệm năng lượng chiếu sáng và sưởi ấm, khi tận dụng ánh sáng ban ngày của ngày làm việc từ sớm, giảm chiếu sáng ban đêm nhờ ngủ sớm. Chính vì ý nghĩa này mà một số nước gọi quy ước này với cái tên "Giờ tiết kiệm ánh sáng ngày" (daylight saving time trong tiếng anh) . Thí dụ tại phần lớn Hoa Kỳ Lục địa và Canada, thời gian sử dụng "giờ tiết kiệm ánh sáng ngày" bắt đầu từ chủ nhật trong tuần thứ hai của tháng 3 đến chủ nhật trong tuần đầu tiên của tháng 11. Như vậy thời kỳ sử dụng giờ tiết kiệm ánh sáng ngày kéo dài gần như 2/3 năm. 2 o Quy ước giờ Mùa Hè được áp dụng đầu tiên tại Ðức từ năm 1916 trong thời gian Thế Chiến Thứ Nhất nhằm tiết kiệm than. Các nước Âu Châu khác sau đó theo chân nhưng cũng có những dư luận phản đối vì cho rằng gây phiền toái, vì vậy đã nhiều lần áp dụng rồi ngưng và rồi áp dụng trở lại. o Hoa Kỳ bắt đầu có quy định giờ Mùa Hè (daylight saving time - DST) từ tháng 3 năm 1918, đến khi Thế Chiến I chấm dứt thì liên bang bãi bỏ quy định chung và một số tiểu bang không theo quy ước này nữa. Ðến Thế Chiến II, Tổng Thống Franklin Roosevelt ấn định dùng giờ DST cho toàn năm trên toàn quốc, nghĩa là lúc nào đồng hồ cũng được vặn sớm lên 1 giờ. Quy định này áp dụng từ 1942 và chấm dứt năm 1945 khi chiến tranh kết thúc. o Một vài nước Phi Châu, Á Châu Á và một số quốc gia Nam Bán Cầu. Các nước vùng nhiệt đới không bao giờ dùng giờ DST vì chênh lệch ngày đêm vào bất cứ tháng nào trong năm rất ít. Nhiều quốc gia khác trước kia đã áp dụng quy ước này ngày nay bãi bỏ vì coi là phiền toái, như trường hợp Nhật Bản, Nam Hàn, Ấn Ðộ, các nước Trung Á, nhiều nước Nam Mỹ và một số tiểu bang Australia. o Trung Quốc nằm trong miền ôn đới nhưng không dùng giờ DST bởi lẽ quốc gia này trải rộng từ Tây sang Ðông trên 4 múi giờ tương tự như Hoa Kỳ nhưng lại quy định chỉ dùng một giờ thống nhất là giờ Bắc Kinh, có nghĩa là ở nhiều vùng, giờ trong ngày đã khác biệt khá xa so với thực tế sáng tối, do đó nếu còn có đổi giờ nữa thì sai biệt sẽ quá lớn. 2. Lớp ZonedDateTime: - Lớp ZonedDateTime: là một lớp đại diện cho thời gian ngày giờ trong một múi giờ cụ thể (giờ địa phương). Lớp này lưu trữ tất cả các thông tin về thời gian, với độ chính xác nano giây, và một múi giờ TimeZone. Ví dụ, giá trị “02 tháng 10 năm 2007 lúc 13:45.30123456789 02 trong múi giờ ở châu Âu/Paris” có thể được lưu trữ trong một ZonedDateTime. - Tạo một đối tượng ZonedDateTime: o Cho một ID time zone, phương thức static ZoneId.of (id) trả về một đối tượng ZoneId. Bạn có thể sử dụng đối tượng ZoneId kết hợp với một đối tượng LocalDateTime để tạo ra một đối tượng ZonedDateTime bằng cách gọi local.atZone(zoneId): ZonedDateTime dateTime = local.atZone(zoneId): o Bằng cách gọi phương thức static ZonedDateTime.of (year, month, day, hour, minute, second, nano, zoneId). Ví dụ: ZonedDateTime apollo11launch = ZonedDateTime.of(1969, 7, 16, 9, 32, 4, 0, 3 ZoneId.of("America/New_York")); 16T09:32-04:00[America/New_York] // 1969-07- o Tạo từ một chuỗi: ZonedDateTime dateTime = ZonedDateTime.pares(“2007-1203T10:15:30+01:00[Europe/Paris]”) o Tạo từ một đối tượng Instant (thời điểm) bằng cách gọi phương thức atZone(ZoneID zone). Ví du: ZonedDateTime newyork = instant.atZone(ZoneId.of( "America/New_York")); - Bảng mô tả các phương thức của ZonedDateTime: Phương thức now, of, ofInstant plusDays, plusWeeks, plusMonths, plusYears, plusHours, plusMinutes, plusSeconds, plusNanos minusDays, minusWeeks, minusMonths, minusYears, minusHours, minusMinutes, minusSeconds, minusNanos plus, minus withDayOfMonth, withDayOfYear, withMonth, withYear, withHour, withMinute, withSecond, withNano withZoneSameInstant, withZoneSameLocal getDayOfMonth getDayOfYear getDayOfWeek getMonth, getMonthValue getYear getHour, getMinute, getSecond, getNano getOffset Mô tả Nhưng phương thức static tạo một ZonedDateTime từ thời điểm hiện tại, hoặc từ một năm, tháng, ngày, giờ, phút, giây, nano giây (hoặc một LocalDate và localtime) và ZoneId, hoặc từ một khoảnh khắc và ZoneId. Thêm một số đơn vị thời gian (ngày, giờ, tháng …) Loại bỏ một số đơn vị thời gian Thêm, bớt một Duration hoặc Period. Trả về một ZonedDateTime mới, với một đơn vị thời gian đã thay đổi đến giá trị nhất định. Trả về một ZonedDateTime mới trong múi giờ nhất định, hoặc là đại diện cho các khu vực cùng một múi giờ. Lấy giá trị ngày của tháng (từ 1 đến 31). Lấy giá trị ngày của năm (từ 1 đến 366). Lấy giá trị các ngày trong tuần, trả về giá trị của một thứ trong tuần Lấy giá trị tên của tháng, hoặc như một số từ 1 đến 12. Gets the year, between –999,999,999 and 999,999,999. Lấy giá trị hour, minute, second, or nanosecond của đối tượng ZonedDateTime. Gets the offset from UTC, as a ZoneOffset instance. Offsets can vary from –12:00 to +14:00. Some time zones have fractional offsets. Offsets change with 4 toLocalDate, toLocalTime, toInstant isBefore, isAfter daylight savings time. Trả về một ngày địa phương hoặc giờ địa phương, hoặc một thời điểm địa phương. So sánh ZonedDateTime với nhau. 3. Một số trường hợp thực tế: - Thời gian DST đưa ra một số sự phiền phức. Khi DST bắt đầu, đồng hồ nhảy lên một giờ. Điều gì sảy ra khi bạn xây dựng một đối tượng thời gian mà rời vào 1 giờ bỏ qua đó? Ví dụ, trong năm 2013, Trung ương châu Âu chuyển sang giờ mùa hè vào ngày 31 tháng 3 lúc 2:00. Nếu bạn cố gắng để xây dựng thời gian không tồn tại ngày 31 tháng 3 02:30, bạn thực sự có được 03:30. ZonedDateTime skipped = ZonedDateTime.of( LocalDate.of(2013, 3, 31), LocalTime.of(2, 30), ZoneId.of("Europe/Berlin")); // kết quả March 31 3:30 Ngược lại, khi DST kết thúc, đồng hồ được đặt lùi lại 1 giờ, và có 2 khoảnh khắc thời gian cùng một giờ địa phương: ZonedDateTime ambiguous = ZonedDateTime.of( LocalDate.of(2013, 10, 27), // End of daylight savings time LocalTime.of(2, 30), ZoneId.of("Europe/Berlin")); // 2013-10-27T02:30+02:00[Europe/Berlin] ZonedDateTime anHourLater = ambiguous.plusHours(1); // 2013-10-27T02:30+01:00[Europe/Berlin] Một giờ sau, thời gian có cùng một giờ và phút, nhưng múi giờ đã thay đổi. Bạn cũng cần phải chú ý khi điều chỉnh một ngày qua ranh giới của DST. Ví dụ, nếu bạn thiết lập một cuộc họp vào tuần tới không thêm Duration.ofDays(7) ví dụ : ZonedDateTime nextMeeting = meeting.plus(Duration.ofDays(7)); // Caution! Won’t work with daylight savings time // Duration - khoảng thời gian Thay vào đó, sử dụng lớp Period. ZonedDateTime nextMeeting = meeting.plus(Period.ofDays(7)); // OK Phần II Câu hỏi trắc nghiệm Câu 1: Lớp ZonedDateTime đại diện cho: A. Giờ địa phương (đáp án đúng) 5 B. Giờ quốc tế C. Múi giờ của một địa phương D. Thời gian theo chuẩn ISO-8601 không gắn với múi giờ Câu 2: Trung ương châu Âu bắt đầu “giờ mùa hè” vào ngày 31 tháng 3 lúc 2:00. Đối tượng “skipped” trong đoạn code sau trả về thời gian( giờ : phút) nào? ZonedDateTime skipped = ZonedDateTime.of( LocalDate.of(2013, 3, 31), // Ngày bắt đầu giờ mùa hè LocalTime.of(2, 30), ZoneId.of("Europe/Berlin")); A. B. C. D. 01:30 02:30 03:30 (đáp án đúng) 04:30 Câu 3: Ở châu Âu kết thúc “giờ mùa hè” vào ngày 27 tháng 10 lúc 2:00. Đối tượng “anHourLater” trong đoạn code sau trả về thời gian( giờ : phút + múi giờ nào) nào? ZonedDateTime ambiguous = ZonedDateTime.of( LocalDate.of(2013, 10, 27), // Ngày kết thúc giờ mùa hè LocalTime.of(2, 30), ZoneId.of("Europe/Berlin")); // 2013-10-27T02:30+02:00[Europe/Berlin] ZonedDateTime anHourLater = ambiguous.plusHours(1); //1 giờ sau A. B. C. D. 01:30+01:00[Europe/Berlin] 02:30+01:00[Europe/Berlin] (đáp án đúng) 01:30+02:00[Europe/Berlin] 02:30+02:00[Europe/Berlin] 6