这是包含一些代码的 Java 8 更新,因为 GregorianCalendar 可能会被弃用或从未来的 JDK 版本中删除。
新代码在WeekFields 类中处理,特别是小写y / 大写Y 使用weekBasedYear() 字段访问器。
基于此返回一个字段以访问基于周的年份
周字段。这代表了周开始的年份的概念
在固定的星期几,例如星期一,每周属于
正好一年。该字段通常与 dayOfWeek() 和
weekOfWeekBasedYear()。
Week one(1) 是从 getFirstDayOfWeek() 开始的那一周,其中
一年中至少有 getMinimalDaysInFirstWeek() 天。 因此,
第一周可能在年初之前开始。如果第一周
在年初之后开始,然后之前的时期在
上一年的最后一周。
此字段可用于任何日历系统。
在解析的解析阶段,可以从
基于周的年、年中的周和周中的日期。
在严格模式下,所有三个字段都根据它们的范围进行验证
有效值。一年中的星期字段经过验证,以确保
生成的基于周的年份是请求的基于周的年份。
在智能模式下,所有三个字段都根据它们的范围进行验证
有效值。基于周数的年份字段从 1 到
53,表示生成的日期可以在以下
以周为基础的年份到指定的年份。
在宽松模式下,根据
有效值的范围。结果日期计算为等价于
以下三个阶段的方法。首先,在第一个上创建一个日期
所请求的基于周的年份的第一周中的某天。然后取
以周为基础的年,减去一,然后以周为单位添加金额
日期。最后,调整到正确的星期几
本地化周。
此WeekFields 实例的设置取决于区域设置,并且可能有不同的设置,取决于它,美国和欧洲国家(如法国)可能有不同的一天作为一周的开始。
例如 Java 8 的 DateFormatterBuilder,使用语言环境实例化解析器,并将该语言环境用于 Y 符号:
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);
}
...
}
...
}
这里有一些例子
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()));
关于区域设置和大写Y,您可以使用命令行选项-Duser.language=(fr、en、es 等),或者强制使用区域设置在调用时:
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)));