Getting the Week Number From Any Date – 从任何日期获取周数

最后修改: 2020年 6月 18日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

In this article, we’ll study several options that we can use in Java to get the week number for a given date. We’ll start by looking at a few options for legacy code using classes prior to Java 8. Afterward, we’ll take a look at the newer Date Time API in the java.time package that was introduced in Java 8.

在这篇文章中,我们将研究在Java中可以使用的几个选项,以获得给定日期的星期数。我们将首先看一下使用Java 8之前的类的遗留代码的几个选项。之后,我们将看看Java 8中引入的java.time包中较新的Date Time API

2. Before Java 8

2.在Java 8之前

Prior to Java 8, date and time calculations were performed mainly using the Date and Calendar classes. Typically we create a Calendar, and then it is possible to extract the information we need from it by using different constants.

在Java 8之前,日期和时间的计算主要是通过DateCalendar类进行的。通常情况下,我们创建一个Calendar,然后可以通过使用不同的常数从其中提取我们需要的信息。

2.1. Get Week Number Using Calendar Fields

2.1.使用Calendar字段获取周号

Let’s look at our first example:

让我们来看看我们的第一个例子。

Calendar calendar = Calendar.getInstance(locale); 
calendar.set(year, month, day); 
int weekOfYear = calendar.get(Calendar.WEEK_OF_YEAR);

We simply create a Calendar instance for the given Locale and set the year, month, and day, and finally, we get the WEEK_OF_YEAR field from the calendar object. This will return the week number within the current year.

我们只需为给定的Locale创建一个Calendar实例,并设置年、月、日,最后,我们从calendar对象中获取WEEK_OF_YEAR字段。这将返回当前年份中的周数。

Now, let’s take a look at how to invoke this method from one of our unit tests:

现在,让我们来看看如何从我们的一个单元测试中调用这个方法。

@Test
public void givenDateUsingFieldsAndLocaleItaly_whenGetWeekNumber_thenWeekIsReturnedCorrectly() {
    Calendar calendar = Calendar.getInstance(Locale.ITALY);
    calendar.set(2020, 10, 22);

    assertEquals(47, calendar.get(Calendar.WEEK_OF_YEAR));
}

We need to be careful when adopting this approach, as the month field in the Calendar class is zero-based. This means if we want to specify December, then we need to use the number 11, which can often lead to confusion.

在采用这种方法时,我们需要小心,因为Calendar类中的月份字段是基于零的。这意味着如果我们想要指定十二月,那么我们需要使用数字11,这往往会导致混淆。

2.2. Get Week Number Using Locale Setups

2.2.使用Locale设置获取周号

In this penultimate example, we’ll take a look at what the effect of applying some additional settings to our Calendar can have:

在这倒数第二个例子中,我们将看看将一些额外的设置应用到我们的Calendar中会产生什么效果。

Calendar calendar = Calendar.getInstance();
calendar.setFirstDayOfWeek(firstDayOfWeek);
calendar.setMinimalDaysInFirstWeek(minimalDaysInFirstWeek);
calendar.set(year, month, day);

int weekOfYear = calendar.get(Calendar.WEEK_OF_YEAR);

The Calendar class defines two methods:

Calendar类定义了两个方法。

  • setFirstDayOfWeek
  • setMinimalDaysInFirstWeek

These methods have an impact on how we calculate the week number. Normally, both these values are taken from the Locale when creating the Calendar. But it is also possible to set the first day in the week and the minimal days in the first week of the year manually.

这些方法对我们计算周数的方式有影响。通常情况下,在创建Calendar时,这两个值都取自Locale但是也可以手动设置一周中的第一天和一年中第一周的最小天数。

2.3. Locale Differences

2.3.地区性差异

Locale plays an important role in how the week number is calculated:

在如何计算周数方面,地域性起着重要作用。

@Test
public void givenDateUsingFieldsAndLocaleCanada_whenGetWeekNumber_thenWeekIsReturnedCorrectly() {
    Calendar calendar = Calendar.getInstance(Locale.CANADA);
    calendar.set(2020, 10, 22);

    assertEquals(48, calendar.get(Calendar.WEEK_OF_YEAR));
}

In this unit test, we’ve only changed the locale of the Calendar to use Locale.CANADA instead of Locale.ITALY and now the week number returned is 48 instead of 47.

在这个单元测试中,我们只改变了Calendar的locale,使用Locale.CANADA而不是Locale.ITALY,现在返回的周数是48而不是47

Both results are correct. As mentioned previously, this happens because each Locale has different settings for the setFirstDayOfWeek and setMinimalDaysInFirstWeek methods.

两个结果都是正确的。如前所述,发生这种情况是因为每个LocalesetFirstDayOfWeeksetMinimalDaysInFirstWeek方法的设置不同

3. Java 8 Date Time API

3 Java 8 Date Time API

Java 8 introduced new APIs for Date and Time to address the shortcomings of the older java.util.Date and java.util.Calendar.

Java 8 为 DateTime 引入了新的 API,以解决旧版 java.util.Datejava.util.Calendar 的不足之处。

In this section, we’ll take a look at some options for getting the week number from the date using this newer API.

在这一节中,我们将看一下使用这个较新的API从日期中获取周数的一些选项。

3.1. Get Week Number Using the Numerical Values

3.1.使用数值获取周号

Likewise, as we saw before with Calendar, we can also pass year, month, and day values directly into LocalDate:

同样地,正如我们之前看到的Calendar,我们也可以将年、月、日的值直接传递到LocalDate

LocalDate date = LocalDate.of(year, month, day);
int weekOfYear = date.get(WeekFields.of(locale).weekOfYear());

The benefit over our pre-Java 8 examples is that we don’t have the problem of the month field being zero-based.

与Java 8之前的例子相比,我们的好处是,我们不存在月份字段为零的问题。

3.2. Get Week Number Using Chronofield

3.2.使用Chronofield获取周号

In this final example we’ll see how to use the ChronoField enumeration, which implements the TemporalField interface:

在最后一个例子中,我们将看到如何使用ChronoField枚举,它实现了TemporalField接口

LocalDate date = LocalDate.of(year, month, day);
int weekOfYear = date.get(ChronoField.ALIGNED_WEEK_OF_YEAR);

This example is similar to using the Calendar.WEEK_OF_YEAR int constant that we saw previously, but using ChronoField.ALIGNED_WEEK_OF_YEAR.

这个例子类似于我们之前看到的使用Calendar.WEEK_OF_YEAR int常量,但使用的是ChronoField.ALIGNED_WEEK_OF_YEAR

4. Conclusion

4.总结

In this quick tutorial, we illustrated several ways of getting the week number from a date using plain Java.

在这个快速教程中,我们说明了使用普通Java从一个日期中获取周数的几种方法。

As always, the full source code of the article is available over on GitHub.

一如既往,文章的完整源代码可在GitHub上获得