«1. Введение

В этой статье мы рассмотрим несколько вариантов, которые мы можем использовать в Java для получения номера недели для заданной даты. Мы начнем с рассмотрения нескольких вариантов устаревшего кода с использованием классов до Java 8. Затем мы рассмотрим более новый API Date Time в пакете java.time, представленном в Java 8.

2. До Java 8

До Java 8 вычисления даты и времени выполнялись в основном с использованием классов Date и Calendar. Обычно мы создаем Календарь, а затем можно извлечь из него нужную нам информацию, используя различные константы.

2.1. Получение номера недели с использованием полей календаря

Давайте посмотрим на наш первый пример:

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

Мы просто создаем экземпляр календаря для данной локали и устанавливаем год, месяц и день, и, наконец, мы получаем поле WEEK_OF_YEAR из объекта календаря. Это вернет номер недели в текущем году.

Теперь давайте посмотрим, как вызвать этот метод из одного из наших модульных тестов:

@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));
}

Мы должны быть осторожны, применяя этот подход, так как поле месяца в классе Calendar отсчитывается от нуля. . Это означает, что если мы хотим указать декабрь, нам нужно использовать число 11, что часто может привести к путанице.

2.2. Получение номера недели с помощью настроек локали

В этом предпоследнем примере мы рассмотрим, какой эффект может иметь применение некоторых дополнительных настроек к нашему календарю:

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

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

Класс Calendar определяет два метода: ~~ ~ setFirstDayOfWeek setMinimalDaysInFirstWeek

    Эти методы влияют на то, как мы вычисляем номер недели. Обычно оба эти значения берутся из локали при создании календаря. Но также возможно установить первый день недели и минимальное количество дней первой недели года вручную.

2.3. Различия локали

Локаль играет важную роль в том, как рассчитывается номер недели:

В этом модульном тесте мы только изменили локаль календаря, чтобы использовать Locale.CANADA вместо Locale.ITALY и теперь возвращается номер недели 48 вместо 47.

@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));
}

Оба результата верны. Как упоминалось ранее, это происходит потому, что каждая локаль имеет разные настройки для методов setFirstDayOfWeek и setMinimalDaysInFirstWeek.

3. Java 8 Date Time API

В Java 8 представлены новые API для даты и времени, чтобы устранить недостатки старых java.util.Date и java.util.Calendar.

В этом разделе мы рассмотрим некоторые варианты получения номера недели из даты с помощью этого нового API.

3.1. Получение номера недели с использованием числовых значений

Аналогично, как мы видели ранее с календарем, мы также можем передавать значения года, месяца и дня непосредственно в LocalDate:

Преимущество по сравнению с нашими примерами до Java 8 заключается в следующем. что у нас нет проблемы с отсчетом поля месяца от нуля.

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

3.2. Получение номера недели с помощью Chronofield

В этом последнем примере мы увидим, как использовать перечисление ChronoField, которое реализует интерфейс TemporalField:

Этот пример похож на использование константы Calendar.WEEK_OF_YEAR int, которую мы видели. ранее, но с использованием ChronoField.ALIGNED_WEEK_OF_YEAR.

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

4. Заключение

В этом кратком руководстве мы проиллюстрировали несколько способов получения номера недели из даты с использованием простой Java.

Как всегда, полный исходный код статьи доступен на GitHub.

«