简单日期格式周年



java8 公历 DOC

一周年与WEEK_OF_YEAR周期同步。第一周和最后一周(含(之间的所有周都具有相同的周年值。因此,一周年的第一天和最后几天可能具有不同的日历年值。

例如,1998 年 1 月 1 日是星期四。如果 getFirstDayOfWeek(( 是 MONDAY,getMinimalDaysInFirstWeek(( 是 4(ISO 8601 标准兼容设置(,则 1998 年第 1 周从 1997 年 12 月 29 日开始,到 1998 年 1 月 4 日结束。1997日历年的最后三天的周年是1998年。但是,如果 getFirstDayOfWeek(( 是 SUNDAY,则 1998 年第 1 周从 1998 年 1 月 4 日开始,到 1998 年 1 月 10 日结束;1998 年的前三天是 1997 年第 53 周的一部分,其周年是 1997 年。

正如DOC所说,如果我将FirstDayOfWeek设置为SUNDAY,将MinimalDaysInFirstWeek设置为4,那么1998-01-01的一周年应该是1997年,但junit结果是1998年。

Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 1998);
calendar.set(Calendar.MONTH, 0);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.setMinimalDaysInFirstWeek(4);
calendar.setFirstDayOfWeek(Calendar.SUNDAY);
System.out.println(calendar.getTimeZone());
System.out.println(calendar.getMinimalDaysInFirstWeek());
System.out.println(calendar.getFirstDayOfWeek());
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
System.out.println(sdf.format(calendar.getTime()));

JUNIT 结果是: sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings = 0,useDaylight=false,transitions=29,lastRule=null]

1

1998年01月01

TL;DR:格式化程序使用自己的周编号

日期格式化程序使用自己的周编号方案,而不是日期的编号方案(在您的情况下是Calendar对象的日期(。我正在使用java.time演示现代Java日期和时间API。具体来说,我正在使用LocalDate.LocalDate始终是 ISO 日历系统中的日期。

LocalDate date = LocalDate.of(1998, Month.JANUARY, 1);
DateTimeFormatter baseFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd");
DateTimeFormatter chinaFormatter = baseFormatter.withLocale(Locale.CHINA);
System.out.println("China:   " + date.format(chinaFormatter));
DateTimeFormatter franceFormatter = baseFormatter.withLocale(Locale.FRANCE);
System.out.println("France:  " + date.format(franceFormatter));
DateTimeFormatter irelandFormatter = baseFormatter.withLocale(Locale.forLanguageTag("en-IE"));
System.out.println("Ireland: " + date.format(irelandFormatter));

此代码段的输出为:

China:   1998-01-01
France:  1998-01-01
Ireland: 1997-01-01
  • 如果默认区域设置为中国,则格式化程序使用的是中国周。它们从星期日开始,第 1 周是包含 1 月 1 日的一周(如在美国,作为另一个示例(。因此,1998 年 1 月 1 日必须属于 1998 周。
  • 法国使用 ISO 编号:一周从星期一开始,正如您所说,在这种情况下,1998 年第 1 周从 1997 年 12 月 29 日开始。所以我们又得到了1998年。
  • 爱尔兰是少数几个使用您在问题中尝试获得的混合方案的国家之一:第一周的最小天数为 4(如 ISO 中(,星期日是一周的第一天(如中国和美国(。因此,使用爱尔兰作为区域设置国家/地区的格式化程序会为您提供您想要获得的结果,即 1997 年。

从您的日期获取 1997 年一周的另一种方法是将您自己的WeekFields对象放在一起。然后,您无需担心区域设置。

WeekFields myWeekFields = WeekFields.of(DayOfWeek.SUNDAY, 4);
int weekYear = date.get(myWeekFields.weekBasedYear());
System.out.println("Week year: " + weekYear);

周年: 1997

java.time??

您使用的日期和时间类,CalendarSimpleDateFormat,设计不佳且早已过时。

从您的文档链接来看,您使用的是Java 8,如果是这样,那么绝对没有理由为旧类而苦苦挣扎。像我上面一样使用 java.time。Java 6 和 7 的向后移植也存在。

为什么问题中的代码不起作用?

您正在使用calendar.getTime()Calendar中抽出时间。这将返回一个Date(另一个设计不佳且早已过时的类(。Date是一个时间点,仅此而已。它没有任何周数或周年的概念。你把这个Date传递给你的SimpleDateFormat,它无法检测到Date最初来自一个Calendar对象,在一周的第一周和第一天有一定的天数设置。相反,SimpleDateFormat使用自己的周定义。它总是这样做。由于您没有明确设置SimpleDateFormat的语言环境或日历,因此它使用了JVM的默认语言环境。这产生了 1998 年的一周,就像在绝大多数地区一样。

最新更新