2014-04-04 12 views
14

Đây là hai lĩnh vực trong gói java.time.temporal:Động lực cho hai định nghĩa dựa trên tuần khác nhau trong JSR-310 là gì?

IsoFields.WEEK_BASED_YEAR

WeekFields.ISO.weekBasedYear()

tiêu chuẩn ISO-8601 định nghĩa một ngày trong tuần cái gọi là bên cạnh hai loại khác trong ngày, cụ thể là ngày lịch thông thường (bao gồm năm, tháng và ngày trong tháng) và ngày thứ tự (bao gồm năm và ngày trong năm). Một weekdate được định nghĩa theo định dạng YYYY-'W'ww-e. w là viết tắt của tuần-của-năm, e cho số ISO-ngày-trong tuần. Y là viết tắt của tuần dựa trên năm và là giống hệt với năm dương lịch với ngoại lệ vào đầu hoặc cuối năm dương lịch, bởi vì một tuần dựa trên năm là ràng buộc với chu kỳ tuần mà cuối cùng có thể bắt đầu trong năm trước. Hai quy tắc quan trọng để hiểu cách một ngày trong tuần được hình thành:

  1. Tuần luôn bắt đầu vào thứ Hai.
  2. Tuần đầu tiên của năm dương lịch là tuần có chứa ít nhất bốn ngày.

Thoạt nhìn, cả hai trường JSR-310 có vẻ giống nhau vì ISO-8601 chỉ đề cập đến một loại dựa trên tuần. Nhưng chờ đợi, bất ngờ. Chúng ta hãy xem xét sau mã ví dụ:

LocalDate date1 = 
    LocalDate.of(2000, 2, 29).with(IsoFields.WEEK_BASED_YEAR, 2014); 
System.out.println("IsoFields-Test: " + date1); // output: 2014-03-01 

LocalDate date2 = 
    LocalDate.of(2000, 2, 29).with(WeekFields.ISO.weekBasedYear(), 2014); 
System.out.println("WeekFields-Test: " + date2); // output: 2014-02-25 

Trong khi tôi rất tốt hiểu sự thay đổi thứ hai tôi thực sự ngạc nhiên khi thấy kết quả khác nhau cho ngày đầu tiên được sử dụng "chính thức" tiêu chuẩn ISO-8601-tài liệu tham khảo trong classname của nó. Để giải thích các kết quả tính toán:

Ngày 2000-02-29 tương ứng với 2000-W09-2 trong ký hiệu ISO-weekdate trong khi 2014-02-25 tương ứng với 2014-W09-2 giữ nguyên tuần-of- năm và ngày trong tuần. Cho đến nay rất tốt. Đặc điểm bảo quản này cho các trường nhỏ hơn tương tự như quy tắc cách thay đổi năm dương lịch (trong hầu hết các trường hợp, nên giữ tháng và ngày trong tháng không thay đổi).

Nhưng kết quả là gì 2014-03-01? Ở đây thuật toán chỉ đơn giản là thêm bốn ngày vào ngày tuần tương ứng để tính đến sự khác biệt trong trường "ngày-tháng" (29 so với 25). Tôi chưa tìm thấy bất kỳ nguồn tài liệu hoặc tài liệu chính thức nào cho hành vi này. Có ai biết nơi chúng ta có thể tìm thấy sự biện minh cho sự khác biệt giữa hai lĩnh vực này? Bất kỳ tài liệu nào có sẵn về hành vi thuật toán?

UPDATE:

Bây giờ tôi cố gắng để kiểm tra tự nhất quán của API mới với biểu hiện này để tìm hiểu nào trong hai lĩnh vực được hỗ trợ tốt hơn:

System.out.println(
    "14 week-based-years later = " 
    + LocalDate.of(2000, 2, 29).plus(14, IsoFields.WEEK_BASED_YEARS)); 

Các đầu ra là 2014-03-01 tương tự như trường hợp được mô tả là IsoFields.WEEK_BASED_YEAR, mặc dù tôi vẫn tìm thấy kết quả 2014-02-25 (= 2014-W09-2) hợp lý hơn nhiều. Vì đơn vị thời gian này cũng được tìm thấy trong lớp IsoFields cho đến nay hành vi này là tự nhất quán trong lớp IsoFields. Có vẻ như một tính năng "không có giấy tờ và không trực quan".

Tôi đang sử dụng phiên bản: java.runtime.version = 1.8.0-b132

Nhiều thử nghiệm:

LocalDate d = LocalDate.of(2014, 3, 1); // 2014-W09-6 
System.out.println(
    "week-of-year in 2014-03-01: " 
    + d.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR)); 
System.out.println(
    "day-of-week in 2014-03-01: " 
    + d.get(ChronoField.DAY_OF_WEEK)); 

LocalDate later = d.plus(14, IsoFields.WEEK_BASED_YEARS); // 2028-03-02 = 2028-W09-4 
System.out.println(
    "14 week-based-years later = " 
    + later); 
System.out.println(
    "week-of-year in " + later + ": " 
    + later.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR)); 
System.out.println(
    "day-of-week in " + later + ": " 
    + later.get(ChronoField.DAY_OF_WEEK)); 

Output:

week-of-year in 2014-03-01: 9 
day-of-week in 2014-03-01: 6 
14 week-based-years later = 2028-03-02 
week-of-year in 2028-03-02: 9 
day-of-week in 2028-03-02: 4 

tôi không nhận ra bất kỳ quy tắc rõ ràng. Cả ngày trong tuần được bảo tồn cũng như ngày trong tháng được bảo tồn trong khi thêm 14 tuần dựa trên năm. Vì vậy, đây là một câu hỏi phụ: Quy tắc đằng sau IsoFields.WEEK_BASED_YEARS là gì? Có lẽ JSR-310-team có thể khai sáng cho chúng tôi?

+0

Nếu bạn tìm thấy lỗi, tôi khuyên bạn nên gửi báo cáo lỗi. – assylias

+0

@assylias cảm ơn gợi ý, về quy tắc cho đơn vị dựa trên tuần có vẻ như là một lỗi, cho câu hỏi đầu tiên tôi không chắc chắn nếu JSR-310-đội đủ điều kiện nó như là lỗi hoặc tính năng. –

+0

2014-W09-6 + 14 tuần nên sản xuất 2028-W09-6, bất kỳ điều gì khác là lỗi! Bạn sẽ không chấp nhận 2014-03-01 + 14 năm dương lịch để sản xuất mọi thứ trừ 2028-03-01, phải không? – chansen

Trả lời

8

Đây là lỗi trong số IsoFields được quản lý để bỏ qua vì phương pháp này chưa được kiểm tra (xin lỗi về điều đó). Phải có rất ít sự khác biệt quan sát được giữa các số IsoFieldsWeekFields.ISO khi được triển khai chính xác.

Xem bug report và bản vá mà cuối cùng sẽ hoạt động thông qua hệ thống và được khắc phục.

Lưu ý, thử nghiệm cho thấy rằng việc nhận được trường là tốt, lỗi chỉ ảnh hưởng đến phương pháp with/adjustInto của WEEK_BASED_YEAR. Các đơn vị WEEK_BASED_YEARS bị ảnh hưởng bởi vì việc bổ sung được thực hiện nội bộ bằng cách tái sử dụng các WEEK_BASED_YEAR bị hỏng.

Cập nhật 2014-08-28: Đây là một trong 14 lỗi java.time fixed in 8u20.

+2

Cảm ơn bạn đã làm rõ. Một câu hỏi còn lại: Ý của bạn chính xác là gì khi nói "rất ít sự khác biệt quan sát được"? Có nên có sự khác biệt nào không? Tôi vẫn tự hỏi tại sao có hai lớp mà 'IsoFields' (các trường liên quan đến tuần trong lớp' IsoFields') chỉ có thể được xem là các trường tuần đặc biệt cho trường hợp ISO của lớp 'WeekFields'. –

+1

Người ta có thể lập luận rằng không nên có hai triển khai nào cả, nhưng chúng ta có chúng hiện tại và chúng không thể bị loại bỏ. Sự khác biệt duy nhất có thể quan sát được là WeekFields hoạt động trên tất cả các hệ thống lịch (bằng cách chuyển đổi sang ISO) trong khi IsoFields chỉ hoạt động trên ISO (và từ chối các hệ thống lịch khác). – JodaStephen

+1

Phải, tôi đã không nghĩ về hỗ trợ hệ thống lịch chung trong 'WeekFields'. Vâng, lịch cách mạng Pháp với 10 ngày trong tuần của nó chắc chắn không được hỗ trợ, nhưng upvoted câu trả lời giác ngộ của bạn. –

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