Перейти к основному содержимому

Получение номера недели с любой даты

· 3 мин. чтения

1. Введение

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

2. До Java 8

До Java 8 вычисления даты и времени выполнялись в основном с использованием классов Date и Calendar . Обычно мы создаем 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

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

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

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

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

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

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

3. API даты и времени Java 8

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

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

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

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

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

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

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

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

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

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

4. Вывод

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

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