JavaRush /Blog Java /Random-VI /Một thư viện trực quan, mạnh mẽ để làm việc với thời gian...
theGrass
Mức độ
Саратов

Một thư viện trực quan, mạnh mẽ để làm việc với thời gian và ngày tháng cuối cùng đã có sẵn trong Java (Phần 2).

Xuất bản trong nhóm
Lần trong ngày
    Vậy hãy tiếp tục nhé. Thực thể tiếp theo sau ngày là thời gian trong ngày, được biểu thị bằng lớp LocalTime . Một ví dụ cổ điển là biểu thị giờ mở cửa của một cửa hàng, chẳng hạn từ 7:00 đến 23:00. Các cửa hàng mở cửa vào thời điểm này trên toàn quốc nhưng thời gian thực tế sẽ thay đổi tùy theo múi giờ.     LocalTime là lớp giá trị chỉ lưu trữ thời gian, không có ngày hoặc múi giờ liên quan. Khi cộng hoặc bớt một khoảng thời gian sẽ bị cắt vào lúc nửa đêm. Tức là 20:00 cộng 6 giờ là 2:00. Sử dụng LocalTime tương tự như LocalDate : LocalTime time = LocalTime.of(20, 30); int hour = date.getHour(); // 20 int minute = date.getMinute(); // 30 time = time.withSecond(6); // 20:30:06 time = time.plusMinutes(3); // 20:33:06     Công cụ sửa đổi có thể hoạt động với LocalTime , nhưng các thao tác thời gian thường không phức tạp đến mức cần phải có công cụ sửa đổi.
Kết hợp ngày và giờ
    Lớp tiếp theo chúng ta sẽ xem xét là LocalDateTime . Lớp giá trị này là sự kết hợp của LocalDateLocalTime . Nó đại diện cho cả ngày và giờ, không có múi giờ.      LocalDateTime có thể được tạo trực tiếp hoặc bằng cách kết hợp ngày và giờ: LocalDateTime dt1 = LocalDateTime.of(2014, Month.JUNE, 10, 20, 30); LocalDateTime dt2 = LocalDateTime.of(date, time); LocalDateTime dt3 = date.atTime(20, 30); LocalDateTime dt4 = date.atTime(time);     Tùy chọn thứ ba và thứ tư sử dụng phương thức atTime() , cung cấp một cách linh hoạt để kết hợp ngày và giờ. Hầu hết các lớp hệ thống ngày và giờ đều có các phương thức "at" có thể được sử dụng khi kết hợp đối tượng của bạn với đối tượng khác để tạo một đối tượng phức tạp hơn. Các phương thức khác của lớp LocalDateTime tương tự như các phương thức của LocalDateLocalTime . Các mẫu đặt tên phương thức tương tự làm cho API dễ học hơn . Bảng này liệt kê tất cả các tiền tố phương thức liên quan: Một thư viện trực quan, mạnh mẽ để làm việc với thời gian và ngày tháng cuối cùng đã có sẵn trong Java (Phần 2).  - 1
Lập tức
    Khi chúng ta xử lý ngày và giờ, chúng ta thường làm việc với năm, tháng, ngày, giờ, phút, giây. Tuy nhiên, đây chỉ là một mô hình thời gian có thể gọi là “con người”. Mô hình thứ hai thường được sử dụng là thời gian “máy” hay “liên tục”. Trong mô hình này, một điểm trên trục thời gian được biểu thị bằng một số lớn. Cách tiếp cận này đơn giản hóa các thuật toán tính toán và được sử dụng để lưu trữ thời gian trong hệ điều hành Unix , trong đó thời gian được biểu thị bằng số giây đã trôi qua kể từ ngày 1 tháng 1 năm 1970. Tương tự, trong Java , thời gian được lưu trữ dưới dạng số mili giây đã trôi qua kể từ ngày 1 tháng 1 năm 1970. Cách tiếp cận máy để tính toán thời gian trong API java.time được cung cấp bởi lớp giá trị Instant . Nó cung cấp khả năng biểu diễn một điểm trên trục thời gian mà không cần tất cả thông tin đi kèm, chẳng hạn như múi giờ. Trên thực tế, lớp này chứa số nano giây đã trôi qua kể từ nửa đêm ngày 1 tháng 1 năm 1970. Instant start = Instant.now(); // произведем вычисления Instant end = Instant.now(); assert end.isAfter(start); //машина времени не сработала     Thông thường, lớp Instant được sử dụng để lưu trữ và so sánh các điểm theo thời gian khi bạn cần lưu trữ thời điểm một sự kiện nào đó xảy ra nhưng bạn không quan tâm đến múi giờ xảy ra sự kiện đó. Trong hầu hết các trường hợp, những gì chúng ta không thể làm với lớp Instant sẽ thú vị hơn những gì chúng ta có thể làm với nó. Ví dụ: các dòng mã sau sẽ đưa ra các ngoại lệ: instant.get(ChronoField.MONTH_OF_YEAR); instant.plus(6, ChronoUnit.YEARS);     Ngoại lệ xảy ra do đối tượng tức thời chỉ lưu trữ số lượng nano giây và không cung cấp khả năng làm việc với các đơn vị thời gian hữu ích hơn cho con người. Để sử dụng các đơn vị đo lường khác, ít nhất bạn phải chỉ định múi giờ.
Múi giờ
    Nguyên tắc về múi giờ được phát triển ở Anh khi việc phát minh ra đường sắt và cải tiến các phương tiện liên lạc khác cho phép mọi người di chuyển khoảng cách đủ để có thể nhận thấy sự khác biệt về thời gian mặt trời. Cho đến thời điểm này, mỗi làng và thành phố sống theo thời gian riêng, thường được đo bằng đồng hồ mặt trời. Bức ảnh này cho thấy một ví dụ về những khó khăn mà điều này dẫn đến - kim màu đỏ trên đồng hồ hiển thị giờ Greenwich và kim đen hiển thị giờ địa phương, chênh lệch nhau 10 phút: Hệ thống múi giờ được phát triển, thay thế giờ mặt trời địa phương Một thư viện trực quan, mạnh mẽ để làm việc với thời gian và ngày tháng cuối cùng đã có sẵn trong Java (Phần 2).  - 2     . Nhưng thực tế quan trọng là các múi giờ được các chính trị gia tạo ra và thường được sử dụng để thể hiện quyền kiểm soát chính trị đối với một khu vực. Giống như bất kỳ chính sách nào, các quy tắc liên quan đến múi giờ thường đi ngược lại logic. Ngoài ra, những quy tắc này có thể thay đổi và thường xuyên thay đổi mà không có bất kỳ cảnh báo nào. Các quy tắc múi giờ được biên soạn bởi một nhóm quốc tế xuất bản Cơ sở dữ liệu múi giờ IANA . Nó chứa mã định danh của từng khu vực trên Trái đất và lịch sử thay đổi múi giờ của nó. Mã nhận dạng trông giống như “Châu Âu/London” hoặc “Mỹ/New_York” . Trước khi API java.time được phát hành, lớp TimeZone được sử dụng để biểu thị múi giờ . Bây giờ ZoneId được sử dụng thay thế . Có hai điểm khác biệt chính giữa chúng. Đầu tiên, ZoneId là bất biến, điều này cho phép lưu trữ các đối tượng của lớp này trong các biến tĩnh, cùng với những thứ khác. Thứ hai, bản thân các quy tắc được lưu trữ trong lớp ZoneRules chứ không phải trong chính ZoneId và để có được chúng, bạn cần gọi phương thức getRules() trên đối tượng lớp ZoneId . Đặc điểm chung của tất cả các múi giờ là độ lệch cố định so với UTC/Greenwich . Bạn thường sử dụng điều này khi nói về sự khác biệt về thời gian giữa các thành phố khác nhau, chẳng hạn như "New York chậm hơn London 5 giờ". Lớp ZoneOffset , hậu duệ của ZoneId , biểu thị sự khác biệt về thời gian với kinh tuyến gốc đi qua Greenwich ở London. Từ quan điểm của nhà phát triển, sẽ thật tuyệt nếu không phải đối mặt với các múi giờ và sự phức tạp của chúng. API java.time cho phép bạn thực hiện việc này miễn là có thể. Bất cứ khi nào có thể, hãy sử dụng các lớp LocalDate, LocalTime, LocalDateTimeInstant . Trường hợp bạn không thể thực hiện nếu không có múi giờ, hãy sử dụng lớp ZonedDateTime . Lớp khoanh vùngDateTimecho phép bạn chuyển đổi ngày và giờ từ đơn vị đo lường của con người mà chúng ta thấy trên lịch và đồng hồ sang đơn vị máy. Do đó, bạn có thể tạo ZonedTimeDate từ lớp Local hoặc từ lớp Instant : ZoneId zone = ZoneId.of("Europe/Paris"); LocalDate date = LocalDate.of(2014, Month.JUNE, 10); ZonedDateTime zdt1 = date.atStartOfDay(zone); Instant instant = Instant.now(); ZonedDateTime zdt2 = instant.atZone(zone);     Một trong những tính năng khó chịu nhất của múi giờ là cái gọi là tiết kiệm thời gian ban ngày. Với Giờ tiết kiệm ánh sáng ban ngày chuyển sang và từ Greenwich, chênh lệch múi giờ của bạn với Greenwich thay đổi hai lần (hoặc nhiều hơn) một năm, thường tăng vào mùa xuân và giảm vào mùa thu. Khi điều này xảy ra, chúng ta phải thay đổi tất cả đồng hồ trong nhà. Trong các lớp java.time , dữ liệu offset được biểu diễn dưới dạng "biến đổi offset" . Vào mùa xuân, điều này gây ra một “khoảng trống” về thời gian, khi một số giá trị thời gian là không thể và ngược lại, vào mùa thu, một số giá trị thời gian xảy ra hai lần. Tất cả điều này được lớp ZonedDateTime hỗ trợ thông qua các phương thức xuất xưởng và phương thức chuyển đổi của nó. Ví dụ: việc thêm một ngày sẽ thêm một ngày hợp lý, ngày này có thể được biểu thị bằng nhiều hơn hoặc ít hơn 24 giờ nếu chúng ta chuyển sang giờ tiết kiệm ánh sáng ban ngày hoặc quay lại. Tương tự, phương thức atStartOfDay() được đặt tên như vậy vì chúng ta không thể đảm bảo rằng ngày sẽ bắt đầu chính xác vào lúc nửa đêm - chúng ta phải tính đến khoảng cách thời gian khi chuyển sang tiết kiệm ánh sáng ban ngày. Và một mẹo cuối cùng về tiết kiệm thời gian ban ngày. Nếu bạn muốn chứng minh rằng bạn đã tính đến sự chồng chéo thời gian trong quá trình chuyển đổi từ mùa hè sang mùa đông (khi cùng một giá trị thời gian xuất hiện hai lần), bạn có thể sử dụng một trong hai phương pháp đặc biệt được thiết kế cho các tình huống như vậy: Các phương pháp này sẽ trả về sớm hơn hoặc muộn hơn zdt = zdt.withEarlierOffsetAtOverlap(); zdt = zdt.withLaterOffsetAtOverlap();     value , nếu đối tượng bị chồng chéo trong quá trình chuyển từ thời gian mùa hè sang mùa đông. Trong tất cả các tình huống khác, giá trị trả về sẽ giống nhau.
Các khoảng thời gian
    Tất cả các lớp chúng ta đã thảo luận trước đó đều hoạt động dưới dạng các điểm trên dòng thời gian. Cần có hai lớp giá trị bổ sung để biểu thị các khoảng thời gian. Lớp Duration biểu thị một khoảng thời gian, được đo bằng giây và nano giây. Ví dụ: “23,6 giây”. Lớp Period biểu thị một khoảng thời gian được tính bằng năm, tháng và ngày. Ví dụ: “3 năm, 2 tháng và 6 ngày.” Những khoảng thời gian này có thể được cộng hoặc trừ khỏi ngày hoặc giờ: Period sixMonths = Period.ofMonths(6); LocalDate date = LocalDate.now(); LocalDate future = date.plus(sixMonths);
Định dạng và phân tích cú pháp
    Toàn bộ gói được thiết kế để định dạng và hiển thị ngày giờ - java.time.format . Gói này xoay quanh lớp DateTimeFormatter và nhà máy DateTimeFormatterBuilder của nó . Các cách phổ biến nhất để tạo trình định dạng là thông qua các phương thức và hằng số tĩnh trong DateTimeFormatter , bao gồm:
  • Các hằng số cho các định dạng phổ biến được mô tả trong ISO, chẳng hạn như ISO_LOCAL_DATE.
  • Các mẫu được xác định bằng các chữ cái, chẳng hạn như ofPattern("dd/MM/uuuu").
  • Các kiểu được bản địa hóa, chẳng hạn như ofLocalizedDate(FormatStyle.MEDIUM).
    Sau khi đã tạo một bộ định dạng, bạn thường sử dụng nó bằng cách chuyển nó sang phương thức lớp ngày tháng thích hợp: DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MM/uuuu"); LocalDate date = LocalDate.parse("24/06/2014", f); String str = date.format(f);     Bằng cách này, mã chịu trách nhiệm định dạng đầu ra ngày tháng sẽ được tách thành một lớp riêng biệt. Nếu bạn cần chỉ định riêng ngôn ngữ để định dạng ngày, hãy sử dụng phương thức định dạng withLocale(Locale) . Các lớp chịu trách nhiệm về lịch, múi giờ và đầu vào/đầu ra của số phân số có các phương thức tương tự. Nếu bạn cần thêm tùy chọn tinh chỉnh, hãy xem tài liệu về lớp DateTimeFormatterBuilder , lớp này cho phép bạn tạo các trình định dạng phức tạp theo từng bước. Nó cũng cho phép bạn thiết lập phân tích cú pháp văn bản không phân biệt chữ hoa chữ thường, bỏ qua một số lỗi phân tích cú pháp, đặt độ lệch và các thành phần tùy chọn.
Điểm mấu chốt
     API java.time là một mô hình toàn diện mới để làm việc với ngày và giờ trong Java SE 8 . Nó đưa các ý tưởng và cách triển khai từ Joda-Time lên một tầm cao mới và cuối cùng cho phép các nhà phát triển tránh sử dụng java.util.DateCalendar . Bây giờ làm việc với ngày và giờ có thể rất thú vị!      Bài báo gốc
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION