Đây là bản cập nhật Java 8 với một số mã, vì GregorianCalendar có thể sẽ không còn được dùng hoặc bị loại bỏ khỏi các phiên bản JDK trong tương lai.
Mã mới được xử lý trong lớp WeekFields
và dành riêng cho trường hợp thấp hơn y
/upper case Y
bằng trình truy cập trường weekBasedYear()
.
Trả về trường để truy cập vào năm của một tuần dựa trên năm dựa trên WeekFields này. Điều này thể hiện khái niệm về năm bắt đầu các tuần vào một ngày cố định trong tuần, chẳng hạn như Thứ Hai và mỗi tuần thuộc về chính xác một năm. Trường này thường được sử dụng với dayOfWeek() và weekOfWeekBasedYear().
Tuần một (1) là tuần bắt đầu từ getFirstDayOfWeek() trong đó có ít nhất getMinimalDaysInFirstWeek() ngày trong năm. Vì vậy, tuần một có thể bắt đầu trước khi bắt đầu năm. Nếu tuần đầu tiên bắt đầu sau đầu năm thì khoảng thời gian trước đó là trong tuần trước của năm trước.
Trường này có thể được sử dụng với bất kỳ hệ thống lịch nào.
Trong giai đoạn phân tích cú pháp phân tích, một ngày có thể được tạo từ tuần, năm, tuần và ngày trong tuần.
Ở chế độ nghiêm ngặt, tất cả ba trường được xác thực dựa trên phạm vi giá trị hợp lệ của chúng. Trường hàng tuần được xác thực để đảm bảo rằng kết quả là tuần theo năm là yêu cầu theo tuần.
Trong chế độ thông minh, tất cả ba trường được xác thực dựa trên phạm vi giá trị hợp lệ của chúng. Trường tuần dựa trên tuần được xác thực từ 1 đến 53, có nghĩa là ngày kết quả có thể nằm trong tuần sau dựa trên năm đó theo quy định.
Trong chế độ khoan dung, năm và ngày trong tuần được xác thực dựa trên dải giá trị hợp lệ . Ngày kết quả được tính tương đương với cách tiếp cận ba giai đoạn sau đây. Trước tiên, hãy tạo ngày vào ngày đầu tiên của tuần đầu tiên trong tuần dựa trên tuần được yêu cầu. Sau đó, lấy năm dựa trên tuần trong tuần, trừ một và thêm số tiền trong tuần tới ngày. Cuối cùng, điều chỉnh theo đúng ngày trong tuần trong tuần địa phương hóa.
Phiên bản WeekFields
này phụ thuộc vào ngôn ngữ và có thể có các cài đặt khác tùy thuộc vào quốc gia này và các quốc gia châu Âu như Pháp có thể có một ngày khác vào đầu tuần.
Ví dụ DateFormatterBuilder
Java 8, nhanh chóng phân tích cú pháp với miền địa phương, và sử dụng locale này cho Y
biểu tượng:
public final class DateTimeFormatterBuilder {
...
private void parsePattern(String pattern) {
...
} else if (cur == 'Y') {
// Fields defined by Locale
appendInternal(new WeekBasedFieldPrinterParser(cur, count));
} else {
...
static final class WeekBasedFieldPrinterParser implements DateTimePrinterParser {
...
/**
* Gets the printerParser to use based on the field and the locale.
*
* @param locale the locale to use, not null
* @return the formatter, not null
* @throws IllegalArgumentException if the formatter cannot be found
*/
private DateTimePrinterParser printerParser(Locale locale) {
WeekFields weekDef = WeekFields.of(locale);
TemporalField field = null;
switch (chr) {
case 'Y':
field = weekDef.weekBasedYear();
if (count == 2) {
return new ReducedPrinterParser(field, 2, 2, 0, ReducedPrinterParser.BASE_DATE, 0);
} else {
return new NumberPrinterParser(field, count, 19,
(count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD, -1);
}
case 'e':
case 'c':
field = weekDef.dayOfWeek();
break;
case 'w':
field = weekDef.weekOfWeekBasedYear();
break;
case 'W':
field = weekDef.weekOfMonth();
break;
default:
throw new IllegalStateException("unreachable");
}
return new NumberPrinterParser(field, (count == 2 ? 2 : 1), 2, SignStyle.NOT_NEGATIVE);
}
...
}
...
}
Dưới đây là một số ví dụ
System.out.format("Conundrum : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("YYYYMMdd'T'HHmms'S'")));
System.out.format("Solution : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmms'S'")));
System.out.format("JVM Locale first day of week : %s%n",
WeekFields.of(Locale.getDefault()).getFirstDayOfWeek());
System.out.format("US first day of week : %s%n",
WeekFields.of(Locale.US).getFirstDayOfWeek());
System.out.format("France first day of week : %s%n",
WeekFields.of(Locale.FRANCE).getFirstDayOfWeek());
System.out.format("JVM Locale min days in 1st week : %s%n",
WeekFields.of(Locale.getDefault()).getMinimalDaysInFirstWeek());
System.out.format("US min days in 1st week : %s%n",
WeekFields.of(Locale.US).getMinimalDaysInFirstWeek());
System.out.format("JVM Locale min days in 1st week : %s%n",
WeekFields.of(Locale.FRANCE).getMinimalDaysInFirstWeek());
System.out.format("JVM Locale week based year (big Y): %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC")).get(WeekFields.of(Locale.FRANCE).weekBasedYear()));
System.out.format("France week based year (big Y) : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC")).get(WeekFields.of(Locale.FRANCE).weekBasedYear()));
System.out.format("US week based year (big Y) : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC")).get(WeekFields.of(Locale.US).weekBasedYear()));
Và trong về miền địa phương và chữ hoa trên Y
, bạn có thể chơi với tùy chọn dòng lệnh -Duser.language=
(fr
, en
, es
, vv), hoặc buộc các miền địa phương vào thời điểm gọi:
System.out.format("English localized : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("YYYYMMdd'T'HHmms'S'", Locale.ENGLISH)));
System.out.format("French localized : %s%n",
ZonedDateTime.of(2015, 12, 30, 0, 0, 0, 0, ZoneId.of("UTC"))
.format(DateTimeFormatter.ofPattern("YYYYMMdd'T'HHmms'S'", Locale.FRENCH)));
Cũng giống như một lưu ý với độc giả trong tương lai: Hành vi này sẽ chỉ xảy ra trong tuần cuối cùng của năm hoặc tuần đầu tiên của năm. – ryvantage