2016-01-11 31 views
9

Các tiêu chuẩn ISO-8601 tiêu chuẩn quốc gia màLịch Java WEEK_OF_YEAR không theo tiêu chuẩn ISO-8601?

"Tuần lễ đầu tiên của một năm là tuần có chứa các Thứ Năm đầu tiên năm (và, do đó, luôn luôn chứa 04 tháng 1)."

Có nghĩa là tuần đầu tiên của năm không phải là ngày đầu tiên trong tháng 1 mà là ngày đầu tiên có chứa 4 ngày vào năm mới.

Theo đó, ngày 11 tháng 1 năm 2016 là vào tuần thứ 2. Here is a list of week numbers for 2016.

Ubuntu phản ánh rằng trong thời gian phụ tùng của nó:

enter image description here

Và lệnh cal làm thêm:

enter image description here

Oracle hỗ trợ nó với tham số "iw" của TO_CHAR:

> select to_char(to_date('11/01/2016','dd/mm/yyyy'),'iw') weekno from dual; 
> WEEKNO 
    02 

Nhưng Java nói Môn, ngày 11 tháng một năm 2016 là tuần # 3

Calendar c = Calendar.getInstance(); 
System.out.println(c.getTime()); 
System.out.println(c.get(Calendar.WEEK_OF_YEAR)); 

Output: 
Mon Jan 11 09:02:35 VET 2016 
3 

Java nghĩ tuần đầu tiên của năm nay là một trong đó chứa tháng Giêng, 1st.

- Có cách nào để Java sử dụng đánh số tuần theo ISO-8601-copliant không?

+1

Đó là ngôn ngữ cụ thể. Đặt 'Locale' thành' Locale.UK' mặc định, cho đúng tuần, 2. – haraldK

+0

Nhưng điều đó sẽ thay đổi những thứ khác bên cạnh số tuần! –

+0

Có, hãy xem câu trả lời của tôi bên dưới để có cách tiếp cận tốt hơn. :-) – haraldK

Trả lời

6

Như tôi đã lưu ý trong nhận xét của mình, hành vi mặc định là ngôn ngữ cụ thể. Một số địa phương sẽ cung cấp cho 3, một số địa phương sẽ cung cấp cho 3, một số địa điểm sẽ cung cấp cho 2.

May mắn thay, bạn có thể chỉ định số ngày phải có trong tuần đầu tiên của năm cho một số Calendar nhất định. Khi bạn viết ở trên, đối với tiêu chuẩn ISO 8601, con số này là 4, do đó đoạn mã sau nên làm việc:

Calendar c = Calendar.getInstance(); 
c.setMinimalDaysInFirstWeek(4); // For ISO 8601 
System.out.println(c.getTime()); 
System.out.println(c.get(Calendar.WEEK_OF_YEAR)); 

này nên làm cho sản lượng đúng bất kể địa điểm.

Kiểm tra đầu ra:

Mon Jan 11 14:54:22 CET 2016 
2 
0

tl; dr

myZonedDateTime.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) 

... và ...

myZonedDateTime.get(IsoFields.WEEK_BASED_YEAR) 

Tránh thừa lớp ngày thời gian

Khi correct Answer by haraldK giải thích, các Calendar định nghĩa của tuần thay đổi theo ngôn ngữ. Trong khi có ý tốt, điều này là khó hiểu.

Bạn nên tránh Calendar và các lớp liên quan như Date. Chúng hiện được thay thế bởi các lớp học java.time.

ISO 8601 tuần

Đối với ISO 8601 week, rõ ràng đó có nghĩa là:

  • Ngày đầu tiên là Thứ Hai, chạy đến Chủ nhật.
  • Số tuần một trong một năm dựa trên tuần chứa Thứ Năm đầu tiên của năm dương lịch.
  • Một tuần dựa trên tuần có 52 hoặc 53 tuần.
  • Số ngày đầu tiên/cuối cùng của năm dương lịch có thể xuất hiện trong năm trước đó/tuần tiếp theo.

java.time

Các java.time lớp bao gồm hỗ trợ hạn chế cho ISO 8601 standard weeks. Gọi phương thức get trên các lớp khác nhau như LocalDateZonedDateTime. Vượt qua các triển khai TemporalField được tìm thấy dưới dạng các hằng số trong lớp IsoFields.

int week = myZonedDateTime.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) ; 
int weekBasedYear = myZonedDateTime.get(IsoFields.WEEK_BASED_YEAR) ; 

ThreeTen-Extra

Thậm chí tốt hơn, thêm thư viện ThreeTen-Extra để dự án của bạn để sử dụng YearWeek lớp.

org.threeten.extra.YearWeek yw = YearWeek.from(myZonedDateTime) ; 

Cẩn thận với các thiết lập phần mềm lịch

Không bao giờ giả định nghĩa của một số tuần. Đảm bảo nguồn của một số như vậy có cùng định nghĩa về tuần với bạn, chẳng hạn như định nghĩa ISO 8601.

Ví dụ: Calendar app supplied by Apple với macOS mặc định theo định nghĩa lịch "Gregorian" trong tuần. Đối với những gì có nghĩa là, tôi không biết là tôi không thể tìm thấy bất kỳ tài liệu về ý định/định nghĩa của họ. Đối với các tuần ISO 8601, bạn phải change a setting away from default.


Về java.time

Khung java.time được xây dựng vào Java 8 và sau đó. Các lớp này thay thế các lớp học ngày giờ legacy phiền hà cũ như java.util.Date, Calendar, & SimpleDateFormat.

Dự án Joda-Time, hiện đang ở maintenance mode, khuyên di chuyển đến các lớp java.time.

Để tìm hiểu thêm, hãy xem Oracle Tutorial. Và tìm kiếm Stack Overflow cho nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310.

Sử dụng JDBC driver tương thích với JDBC 4.2 hoặc cao hơn, bạn có thể trao đổi java.time đối tượng trực tiếp với cơ sở dữ liệu của bạn. Không cần chuỗi và các lớp java.sql. *.

Nơi lấy các lớp java.time?

  • Java SE 8, Java SE 9, và sau đó
    • Built-in.
    • Một phần của API Java chuẩn với gói được triển khai.
    • Java 9 thêm một số tính năng và bản sửa lỗi nhỏ.
  • Java SE 6Java SE 7
    • Hầu hết các chức năng java.time được back-chuyển đến Java 6 & 7 trong ThreeTen-Backport.
  • Android
    • phiên bản sau của triển khai bó Android của các lớp java.time.
    • Đối với Android trước đó, dự án ThreeTenABP thích hợp ThreeTen-Backport (đã đề cập ở trên). Xem How to use ThreeTenABP….

Dự án mở rộng ThreeTen-Extra java.time với các lớp bổ sung. Dự án này là một nền tảng chứng minh cho những bổ sung có thể có trong tương lai vào java.time. Bạn có thể tìm thấy một số lớp học hữu ích tại đây như Interval, YearWeek, YearQuartermore.

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