SimpleDateFormat 上周是一年中的第几周错误

ACV*_*ACV -2 java date java-7

我需要获取给定日期的一年中的第几周。使用 SimpleDateFormat 会产生一年中最后一周的错误结果。

例子:

这会正确生成第 52 周:

SimpleDateFormat w = new SimpleDateFormat("w");
Calendar c = Calendar.getInstance();
c.set(2021, 11, 25);
System.out.println("Week: ${w.format(c.getTime())}");
Run Code Online (Sandbox Code Playgroud)

产生:Week: 52

但第二天已经被视为明年的第一周了?

SimpleDateFormat w = new SimpleDateFormat("w");
Calendar c = Calendar.getInstance();
c.set(2021, 11, 26);
System.out.println("Week: ${w.format(c.getTime())}");
Run Code Online (Sandbox Code Playgroud)

产生:Week: 1

这只发生在 Java 7 中,而不发生在 Java 8 及更高版本中!

rzw*_*oot 5

不要使用Calendar. 它已经过时了,而且更重要的是,API非常糟糕。

有一份与我的腿一样长的清单,说明它出了什么问题。这里有大约 200 个相关的事情,其中​​具体的一个是,愚蠢的是,它的月份值是0索引的。那么,“12、3”?那是 12 月 3 日,或者随便你怎么称呼第 13 个月。或者日历不包含第 13 个月,在这种情况下,它会宽大地假设您的意思是说 2022 年 1 月 3 日。不管怎样,这都是第一周。

那么为什么 12 月 2 日(或者如果您愿意的话,通过延期,2022 年 1 月 2 日)是“第 52 周”?

因为它是

周编号很奇怪,但必须如此。一周从星期一开始(或星期日,对于我热爱美国弟兄的愚蠢标准来说),并且不能从其他任何一天开始。这意味着除非 1 月 1 日恰好是星期一,否则就会出现奇怪的情况;2021 年中的天数算作“2022 年第 1 周”,或 2022 年中的天数算作“2021 年第 52 周”。事实上,有时必须有 53 周。毕竟,52*7 是 364,但一年有 365.2475 天,所以除非你只是想让某些日子消失,否则每个因此,通常需要 53 周才能将这一切加起来。

改用java.time.

LocalDate ld = LocalDate.of(2021, 12, 3);
WeekFields wf = WeekFields.of(Locale.ENGLISH);
int weekNumber = ld.get(wf.weekOfWeekBasedYear());
Run Code Online (Sandbox Code Playgroud)

java.time 做了很多事情,非常棒,其中一件很棒的事情是它往往不会隐藏复杂的事情。例如,“一周从什么时候开始”就无法回答,除非你告诉我你在地球上的哪个地方问这个问题。因此,“现在是哪一周”实际上也不是一个可以回答的问题,除非你确切地告诉我我们正在使用哪个周计数系统,并且没有足够普遍接受的标准。因此,您必须通过创建一个单独的WeekFields实例来捕获该信息的繁琐过程。我们在这里根据语言环境进行操作。