Неожиданный результат расчета даты

У меня есть метод для просмотра календаря в Java, который рассчитывает дату по году, день недели и номер недели.

Теперь, когда я рассчитываю даты с 2017 года, все работает. Но когда я рассчитываю даты с января 2018 года, он принимает даты 2017 года.

Мой код выглядит

import java.time.temporal.IsoFields;
import java.time.temporal.ChronoField;
import java.time.LocalDate;

// .....

LocalDate desiredDate = LocalDate.now()
                    .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 1)
                    .with(ChronoField.DAY_OF_WEEK, 1)
                    .withYear(2018);

Что приводит к 2018-01-02 и должно быть 2018-01-01. Как это возможно?

1 ответ

Решение

Порядок вызываемых методов, кажется, имеет значение.
Если вы вызываете их по убыванию времени детализации (год, неделя недели и день недели), вы получите правильный результат:

long weekNumber = 1;
long dayOfWeek = 1;
int year = 2018;

LocalDate desiredDate = LocalDate.now()
    .withYear(year)
    .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber)
    .with(ChronoField.DAY_OF_WEEK, dayOfWeek );

System.out.println(desiredDate);

2018-01-01

Обратите внимание, что источником проблемы является:

.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber)

который устанавливает номер недели (1 to 53) по текущему году.
Ява LocalDate API не может адаптировать это значение, если вы измените год с .withYear(year) так как информация о номере недели не хранится в LocalDate пример.

Вы действительно можете увидеть в LocalDate реализация, которая LocalDate экземпляры определяются только 3 полями: year, month а также day,

public final class LocalDate
        implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable {
    ...
    private final int year;
    /**
     * The month-of-year.
     */
    private final short month;
    /**
     * The day-of-month.
     */
    private final short day;
    ...
}

Поэтому, чтобы быть точным, важно то, что:

.withYear(year) быть вызванным раньше

.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber);

Я хочу упомянуть, что есть еще одна проблема (?) С LocalDate.

Этот код также создает неправильный результат:

    int jahr = Integer.parseInt(str[0]);
    int woche = Integer.parseInt(str[1]);

    LocalDate year = LocalDate.of(jahr, 1, 1);
    LocalDate week = year.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, woche);
    LocalDate day = week.with(wochentag);
    return day;

Если вы измените создание year переменная к

 LocalDate year = LocalDate.now().withYear(jahr);

код возвращает ожидаемый результат. Кажется, как способ создания LocalDate имеет значение. Я предполагаю, что часовой пояс опущен в версии ".of()".

Другие вопросы по тегам