Sự khác nhau giữa API thời gian ngày Java 8 (java.time) và Joda-Time


264

Tôi biết có những câu hỏi liên quan đến java.util.Date và Joda-Time. Nhưng sau khi đào bới, tôi không thể tìm thấy một chủ đề về sự khác biệt giữa API java.time (mới trong Java 8 , được định nghĩa bởi JSR 310 ) và Joda-Time .

Tôi đã nghe nói rằng API java.time của Java 8 sạch hơn nhiều và có thể làm được nhiều hơn Joda-Time. Nhưng tôi không thể tìm thấy ví dụ so sánh hai.

  • Java.time có thể làm gì mà Joda-Time không thể?
  • Java.time có thể làm gì tốt hơn Joda-Time?
  • Hiệu suất có tốt hơn với java.time không?

8
Không phải, đó là liên quan đến Java 7, không phải Java 8. Câu trả lời cho câu hỏi đó đã được chỉnh sửa cho Java 8 với rất ít chi tiết. Câu hỏi của tôi cụ thể là hỏi về API DateTime mới của Java 8, chứ không phải java.util.Date của Java 7. Tôi chỉ tìm kiếm một câu trả lời so sánh Java 8 với JodaTime.
Zack

2
có lẽ tài liệu này của Oracle có thể giúp bạn.
MarioDS

Nếu bạn có Java 7, hãy sử dụng thư viện bổ sung, nếu bạn có Java 8, hãy sử dụng thư viện tích hợp. Vì cả hai thư viện đều được thiết kế cơ bản bởi cùng một người, tôi không chắc bạn đang mong đợi sự khác biệt lớn nào.
Peter Lawrey

2
@PeterLawrey: Joda-Time và API ngày và giờ Java 8 thực sự khá khác nhau.
jarnbjo

5
Bạn cũng có thể đọc bài đăng trên blog này từ Stephen Colbourne - tác giả chính của cả hai dự án.
Matt Johnson-Pint

Câu trả lời:


416

Đặc điểm chung

a) Cả hai thư viện đều sử dụng các loại bất biến. Joda-Time cũng cung cấp các loại đột biến bổ sung như MutableDateTime.

b) Hơn nữa: Cả hai thư viện đều được truyền cảm hứng từ nghiên cứu thiết kế "TimeAndMoney" từ Eric Evans hoặc ý tưởng từ Martin Fowler về phong cách điều khiển tên miền để họ cố gắng ít nhiều cho phong cách lập trình trôi chảy (mặc dù không phải lúc nào cũng hoàn hảo ;-)).

c) Với cả hai thư viện, chúng tôi nhận được một loại ngày theo lịch thực (được gọi LocalDate), loại thời gian tường thực (được gọi LocalTime) và thành phần (được gọi LocalDateTime). Đó là một chiến thắng rất lớn so với cũ java.util.Calendarjava.util.Date.

d) Cả hai thư viện đều sử dụng cách tiếp cận tập trung vào phương thức, nghĩa là họ khuyến khích người dùng sử dụng getDayOfYear()thay vì get(DAY_OF_YEAR). Điều này gây ra rất nhiều phương thức bổ sung so với java.util.Calendar(mặc dù sau này không an toàn về kiểu do sử dụng quá nhiều ints).

Hiệu suất

Xem câu trả lời khác của @ OO7 chỉ vào phân tích của Mikhail Vorontsov mặc dù điểm 3 (bắt ngoại lệ) có thể đã lỗi thời - hãy xem lỗi JDK này . Hiệu suất khác nhau (có lợi cho chung của JSR-310 ) chủ yếu là do việc triển khai nội bộ của Joda-Time luôn sử dụng thời gian dài nguyên thủy giống như thời gian của máy (tính bằng mili giây).

Vô giá trị

Joda-Time thường sử dụng NULL làm mặc định cho múi giờ hệ thống, ngôn ngữ mặc định, dấu thời gian hiện tại, v.v. trong khi JSR-310 hầu như luôn từ chối các giá trị NULL.

Độ chính xác

JSR-310 xử lý độ chính xác nano giây trong khi Joda-Time bị giới hạn ở độ chính xác mili giây .

Các lĩnh vực được hỗ trợ:

Tổng quan về các trường được hỗ trợ trong Java-8 (JSR-310) được đưa ra bởi một số lớp trong gói tạm thời (ví dụ ChronoFieldWeekFields ) trong khi Joda-Time khá yếu trên khu vực này - xem DateTimeFieldType . Sự thiếu hụt lớn nhất của Joda-Time là ở đây sự vắng mặt của các lĩnh vực liên quan đến tuần địa phương. Một đặc điểm chung của cả hai thiết kế triển khai trường là cả hai đều dựa trên các giá trị của loại dài (không có loại nào khác, thậm chí không có enum).

Enum

JSR-310 cung cấp các enum như DayOfWeekhoặc Monthtrong khi Joda-Time không cung cấp điều này bởi vì nó chủ yếu được phát triển trong những năm 2002-2004 trước Java 5 .

API khu vực

a) JSR-310 cung cấp nhiều tính năng múi giờ hơn Joda-Time. Latter không thể mang lại quyền truy cập theo chương trình vào lịch sử của các chuyển đổi bù múi giờ trong khi JSR-310 có khả năng thực hiện điều này.

b) Để biết thông tin của bạn: JSR-310 đã chuyển kho lưu trữ múi giờ bên trong của nó sang một vị trí mới và một định dạng khác. Thư mục thư viện cũ lib / zi không còn tồn tại nữa.

Điều chỉnh so với tài sản

JSR-310 đã giới thiệu TemporalAdjustergiao diện như một cách chính thức để ngoại hóa các tính toán và thao tác tạm thời, đặc biệt đối với thư viện hoặc người viết khung, đây là một cách dễ dàng và tương đối dễ dàng để nhúng các phần mở rộng mới của JSR-310 (một loại tương đương với trình trợ giúp tĩnh lớp học trước đây java.util.Date).

Tuy nhiên, đối với hầu hết người dùng, tính năng này có giá trị rất hạn chế vì gánh nặng để viết mã vẫn thuộc về người dùng. Các giải pháp tích hợp dựa trên nhận thức mới TemporalAdjusterkhông nhiều, hiện tại chỉ có lớp người trợ giúp TemporalAdjustersvới một bộ thao tác giới hạn (và enum Monthhoặc các loại thời gian khác).

Joda-Time cung cấp gói trường nhưng thực tế đã cho thấy bằng chứng cho thấy việc triển khai trường mới rất khó mã hóa. Mặt khác, Joda-Time cung cấp các thuộc tính được gọi là làm cho một số thao tác dễ dàng và thanh lịch hơn nhiều so với trong JSR-310, ví dụ property.withMaximumValue () .

Hệ thống lịch

JSR-310 cung cấp thêm 4 hệ thống lịch. Điều thú vị nhất là Umalqura (được sử dụng ở Ả Rập Saudi). 3 người còn lại là: Minguo (Đài Loan), Nhật Bản (chỉ có lịch hiện đại kể từ năm 1871!) Và ThaiBuddhist (chỉ đúng sau năm 1940).

Joda-Time cung cấp lịch Hồi giáo dựa trên cơ sở tính toán - không phải là lịch dựa trên tầm nhìn như Umalqura. Thái-Phật cũng được cung cấp bởi Joda-Time trong một hình thức tương tự, Minguo và tiếng Nhật không. Mặt khác, Joda-Time cũng cung cấp lịch coptic và ethiopic (nhưng không có bất kỳ sự hỗ trợ nào cho việc quốc tế hóa).

Thú vị hơn đối với người châu Âu: Joda-Time cũng cung cấp lịch Gregorian , Julian và hỗn hợp gregorian-julian. Tuy nhiên, giá trị thực tế cho các tính toán lịch sử thực tế bị hạn chế vì các tính năng quan trọng như năm bắt đầu khác nhau trong lịch sử ngày không được hỗ trợ (cùng một lời chỉ trích là hợp lệ đối với cũ java.util.GregorianCalendar).

Lịch khác như tiếng Hebrew hoặc Ba Tư hay Ấn Độ giáo là hoàn toàn mất tích trong cả hai thư viện.

Ngày kỷ nguyên

JSR-310 có lớp JulianFields trong khi Joda-Time (phiên bản 2.0) cung cấp một số phương thức trợ giúp trong lớp DateTimeUtils .

Đồng hồ

JSR-310 không có giao diện (lỗi thiết kế) mà là một lớp trừu tượng java.time.Clockcó thể được sử dụng cho bất kỳ phép tiêm phụ thuộc đồng hồ nào. Joda-Time cung cấp giao diện MillisProvider và một số phương thức trợ giúp trong DateTimeUtils thay thế. Vì vậy, cách này Joda-Time cũng có khả năng hỗ trợ các mô hình điều khiển thử nghiệm với các đồng hồ khác nhau (chế nhạo, v.v.).

Số học thời lượng

Cả hai thư viện đều hỗ trợ tính toán khoảng cách thời gian trong một hoặc nhiều đơn vị thời gian. Tuy nhiên, khi xử lý thời lượng một đơn vị, kiểu JSR-310 rõ ràng là đẹp hơn (và dựa trên dài thay vì sử dụng int):

JSR-310 => long days = ChronoUnit.DAYS.between(date1, date2);

Thời gian Joda => int days = DAYS.daysBetween(date1, date2).getDays();

Xử lý nhiều đơn vị thời lượng cũng khác nhau. Ngay cả các kết quả tính toán cũng có thể khác nhau - hãy xem vấn đề Joda-Time đã đóng này . Trong khi JSR-310 sử dụng một cách tiếp cận rất đơn giản và hạn chế để chỉ sử dụng các lớp Period(thời lượng dựa trên năm, tháng và ngày) và Duration(dựa trên giây và nano giây), Joda-Time sử dụng cách thức tinh vi hơn để sử dụng lớp PeriodTypeđể kiểm soát trong đó các đơn vị thời lượng (Joda-Time gọi là "Thời gian") sẽ được thể hiện. Trong khiPeriodType-API bằng cách nào đó lúng túng khi sử dụng một cách tương tự không được cung cấp bởi JSR-310. Đặc biệt, vẫn chưa có khả năng trong JSR-310 để xác định thời lượng ngày và thời gian hỗn hợp (ví dụ dựa trên ngày và giờ). Vì vậy, được cảnh báo nếu di chuyển từ thư viện này sang thư viện khác. Các thư viện trong cuộc thảo luận không tương thích - mặc dù có cùng một tên lớp.

Khoảng

JSR-310 không hỗ trợ tính năng này trong khi Joda-Time có hỗ trợ hạn chế. Xem thêm câu trả lời SO này .

Định dạng và phân tích cú pháp

Cách tốt nhất để so sánh cả hai thư viện là xem các lớp có tên bằng nhau DateTimeFormatterBuilder (JSR-310) và DateTimeFormatterBuilder (Joda-Time). Biến thể JSR-310 mạnh hơn một chút (cũng có thể xử lý bất kỳ loại TemporalFieldcung cấp nào mà người triển khai trường đã quản lý để mã hóa một số điểm mở rộng như giải quyết () ). Tuy nhiên, sự khác biệt quan trọng nhất - theo ý kiến ​​của tôi:

JSR-310 có thể phân tích tên múi giờ tốt hơn nhiều (ký hiệu mẫu định dạng z) trong khi Joda-Time hoàn toàn không thể làm điều này trong các phiên bản trước đó và bây giờ chỉ trong một cách rất hạn chế.

Một ưu điểm khác của JSR-310 là hỗ trợ các tên tháng độc lập, quan trọng trong các ngôn ngữ như tiếng Nga hoặc tiếng Ba Lan, v.v. Joda-Time không có quyền truy cập vào các tài nguyên đó - ngay cả trên các nền tảng Java-8.

Cú pháp mẫu trong JSR-310 cũng linh hoạt hơn so với Joda-Time, cho phép các phần tùy chọn (sử dụng dấu ngoặc vuông), được định hướng nhiều hơn theo tiêu chuẩn CLDR và ​​cung cấp phần đệm (ký hiệu chữ p) và nhiều trường hơn.

Mặt khác, cần lưu ý rằng Joda-Time có thể định dạng thời lượng bằng cách sử dụng periodFormatter . JSR-310 không thể làm điều này.


Hy vọng tổng quan này giúp. Tất cả các thông tin thu thập được chủ yếu ở đó do những nỗ lực và điều tra của tôi về cách thiết kế và thực hiện một thư viện ngày giờ tốt hơn (không có gì là hoàn hảo).

Cập nhật từ 2015-06-24:

Trong khi đó, tôi đã tìm thấy thời gian để viết và xuất bản một tổng quan dạng bảng cho các thư viện thời gian khác nhau trong Java. Các bảng cũng chứa một so sánh giữa Joda-Time v2.8.1 và Java-8 (JSR-310). Nó chi tiết hơn bài này.


12
Đây là một bài viết nổi bật. Rất cám ơn đã chia sẻ tất cả các thông tin này. Nếu được lựa chọn giữa Joda và JSR-310 (chỉ dành cho các trường hợp sử dụng vanilla), bạn sẽ chọn cái nào? Tôi đang đối mặt với sự lựa chọn này ngay bây giờ. Tôi đang xem xét JSR-310, chỉ vì nó mới hơn và tôi cố gắng hỗ trợ "tiến về phía trước" bất cứ khi nào có thể.
kevinarpe

7
@kevinarpe Nếu tôi chỉ có sự lựa chọn giữa JSR-310 và Joda-Time, tôi có thể thích JSR-310 hơn vì Joda-Time gần như đã dừng bất kỳ sự phát triển nào nữa (các tính năng lớn mới có thể được mong đợi - chỉ cần sửa lỗi và cập nhật nhỏ). Và thiết kế của JSR-310 đơn giản là hiện đại hơn (và với chất lượng bên trong tốt hơn). Tuy nhiên, nhân tiện và không có gì đáng ngạc nhiên, quyết định thực sự của tôi là thích thư viện Time4J của riêng tôi - xem thêm liên kết đến tổng quan dạng bảng được đưa ra ở cuối bài. Nó luôn luôn tốt để có các lựa chọn thay thế, và nó phụ thuộc mạnh mẽ vào những tính năng bạn cần.
Meno Hochschild

Không phải là phiên bản Thời lượng của Java8?
Christian Hujer

1
@ChristianHujer Không, java.time.Durationkhông thể truy vấn bắt đầu hoặc kết thúc, ngược lại với một khoảng thời gian được neo trên dòng thời gian. Kiểu JSR-310 này chỉ là một cặp giây trôi qua và nano giây kể từ khi bắt đầu không xác định.
Meno Hochschild

42

Java 8 Ngày / Giờ:

  1. Các lớp Java 8 được xây dựng vào khoảng thời gian của con người. Nó làm cho chúng nhanh chóng cho các số liệu / chuyển đổi dữ liệu thời gian của con người.
  2. Các biểu đồ thành phần ngày / giờ như getDayOfMonthcó độ phức tạp O (1) trong triển khai Java 8.
  3. Phân tích cú pháp OffsetDateTime/ OffsetTime/ ZonedDateTimerất chậm trong Java 8 ea b121 do các ngoại lệ được ném và bị bắt trong nội bộ trong JDK.
  4. Một tập hợp các gói: java.time.*, java.time.chrono.*, java.time.format.*, java.time.temporal.*,java.time.zone.*
  5. Instants (dấu thời gian) Ngày và thời gian Một phần ngày và thời gian Trình phân tích cú pháp và định dạng Múi giờ Thời gian khác nhau (lịch).
  6. Các lớp hiện tại có các vấn đề như Ngày không hỗ trợ cho I18N hoặc L10N. Họ là đột biến!
  7. Đơn giản hơn và mạnh mẽ hơn.
  8. Đồng hồ có thể được tiêm.
  9. Đồng hồ có thể được tạo ra với các thuộc tính khác nhau - Đồng hồ tĩnh, Đồng hồ giả, Đồng hồ có độ chính xác thấp (toàn bộ giây, toàn bộ phút, v.v.).
  10. Đồng hồ có thể được tạo ra với các múi giờ cụ thể. Clock.system(Zone.of("America/Los_Angeles")).
  11. Làm cho mã xử lý ngày và thời gian kiểm tra.
  12. Làm cho các bài kiểm tra độc lập với múi giờ.

Joda-Thời gian:

  1. Joda-Time đang sử dụng thời gian máy bên trong. Việc thực hiện thủ công dựa trên các giá trị int / long sẽ nhanh hơn nhiều.
  2. Joda-Time getters yêu cầu tính toán thời gian từ máy tính đến con người trên mỗi cuộc gọi getter, điều này làm cho Joda-Time trở thành nút cổ chai trong các tình huống như vậy.
  3. Nó bao gồm các lớp không thay đổi, nó xử lý Instants, Date & Time, Partials và Durations Nó rất linh hoạt Nó được thiết kế tốt.
  4. Đại diện cho ngày là instants. Nhưng một ngày và thời gian có thể tương ứng với nhiều hơn một tức thì. Chồng chéo giờ khi tiết kiệm ánh sáng ban ngày kết thúc. Cũng như không có bất kỳ tức thì tương ứng với nó. Khoảng cách giờ khi ánh sáng ban ngày bắt đầu. Phải thực hiện các tính toán phức tạp cho các hoạt động đơn giản.
  5. Chấp nhận null là giá trị hợp lệ trên hầu hết các phương thức của nó. Dẫn đến lỗi tinh tế.

Để so sánh chi tiết hơn, xem: -

Hiệu suất thư viện Ngày / Giờ của Java 8 (cũng như Joda-Time 2.3 và juCalWiki) . & API ngày & giờ mới trong Java 8


Khi bạn nói "Làm cho các bài kiểm tra độc lập với múi giờ." chính xác thì ý bạn là gì khi nói vậy?
Zack

@Zack: Có thể là nếu bạn kiểm tra mã, hoạt động khác nhau tùy theo múi giờ, bạn có thể buộc phải kiểm tra để chạy với múi giờ mặc định khác với hệ điều hành được cung cấp.
jarnbjo

Hah - Tôi nghĩ bạn đã nói rằng joda bên trong chạy trên một cỗ máy thời gian chứ không phải thời gian của máy ... Và tôi sẽ không ngạc nhiên
Kyranstar

4
@ OO7 Ý bạn là 'thời gian của con người' là gì? Thời gian được tính bằng máy nào.
IgorGanapolsky

1

Joda-Time hiện đang ở chế độ bảo trì

Không phải là một câu trả lời trực tiếp cho câu hỏi nhưng dự án Joda-Time không còn được phát triển tích cực. Nhóm đề nghị người dùng chuyển sang API java.time mới hơn . Xem hướng dẫn của Oracle .

Từ trang dự án GitHub chính thức :

Joda-time không còn được phát triển tích cực ngoại trừ việc cập nhật dữ liệu múi giờ. Từ Java SE 8 trở đi, người dùng được yêu cầu chuyển sang java.time (JSR-310) - một phần cốt lõi của JDK thay thế cho dự án này. Đối với người dùng Android, java.time được thêm vào API 26+. Các dự án cần hỗ trợ các cấp API thấp hơn có thể sử dụng thư viện ThreeTenABP.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.