Java Календарь выпуска с добавлением года - PullRequest
1 голос
/ 27 февраля 2020

Я пытаюсь добавить год к дате, но которая дает одну и ту же дату для разных входов. Даты ввода: 28 февраля / 2020 и 29 февраля / 2020, а выходные данные для них совпадают с 28/20/2021 . Пожалуйста, помогите мне найти, что здесь не так.

Обновление:

Ожидается выходной результат 28 февраля / 2021 и 01 марта 2021 года.

public static Date dateAdd(Date newDate, int field, int amount) {
        Calendar aCalendar = Calendar.getInstance();
        aCalendar.setTime(newDate);
        aCalendar.add(field, amount);
        return aCalendar.getTime();
    }

    public static void main(String[] args) throws Exception {

        System.out.println(dateAdd(new SimpleDateFormat("dd/MM/yyyy").parse("28/02/2020"),Calendar.YEAR,1));
        System.out.println(dateAdd(new SimpleDateFormat("dd/MM/yyyy").parse("29/02/2020"),Calendar.YEAR,1));

        // Console output below

        //Sun Feb 28 00:00:00 IST 2021
        //Sun Feb 28 00:00:00 IST 2021
    }

Ответы [ 5 ]

5 голосов
/ 27 февраля 2020

После просмотра документации добавьте и roll . Ясно, что то, что вы ищете, можно найти в списке, а не добавить.

Далее, после некоторых исследований топи c я обнаружил, что данный сценарий также зависит от бизнеса и зависит от того, что делать. вы хотите сделать, потому что add и roll дает вам возможность выбрать любой из них.

Я нашел this при поиске похожая проблема у меня была.

Возвращаясь к вашему коду, необходимо внести следующие изменения.

aCalendar.roll(field, amount);

Кто-то еще, кто сможет вам помочь, поможет разобраться в этом ответе. Для меня JavaDocs были не очень понятны, поэтому у следующего вопроса есть несколько интересных ответов

2 голосов
/ 27 февраля 2020

В этом нет ничего плохого, это зависит от интерпретации "добавление одного года", для java.util.Calendar#add это:

add (f, delta) добавляет delta в поле f. Это эквивалентно вызову set(f, get(f) + delta) с двумя настройками:

Добавить правило 1. Значение поля f после вызова минус значение поля f до вызова дельта, по модулю любое переполнение, которое произошло в поле f. Переполнение происходит, когда значение поля превышает его диапазон, и в результате следующее большее поле увеличивается или уменьшается, а значение поля возвращается в его диапазон.

Добавить правило 2. Если ожидается, что поле меньшего размера будет инвариантным, но для него невозможно быть равным его предыдущему значению из-за изменений его минимума или максимума после изменения поля f или других ограничений, таких как изменение смещения часового пояса, то его значение настроен так, чтобы быть как можно ближе к ожидаемому значению. Меньшее поле представляет меньшую единицу времени. HOUR - это поле меньше, чем DAY_OF_MONTH. Не вносятся изменения в меньшие поля, которые не должны быть инвариантными. Календарная система определяет, какие поля должны быть инвариантными.

Кроме того, в отличие от set (), add () вызывает немедленный пересчет миллисекунд календаря и всех полей.

Пример : рассмотрим GregorianCalendar, изначально установленный на 31 августа 1999 года. При вызове add (Calendar.MONTH, 13) календарь устанавливается на 30 сентября 2000 года. Правило добавления 1 устанавливает для поля MONTH значение сентября, а для добавления 13 месяцев - август дает сентябрь следующего года. Так как DAY_OF_MONTH не может быть 31 в сентябре в GregorianCalendar, правило добавления 2 устанавливает для DAY_OF_MONTH значение 30, наиболее близкое возможное значение. Хотя это поле меньшего размера, DAY_OF_WEEK не корректируется по правилу 2, поскольку ожидается, что оно изменится, когда месяц изменится в GregorianCalendar.

Источник: https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html

Звучит в соответствии с описанным поведением, что и почему вы ожидаете? Может быть, есть лучшие / более специализированные решения.

2 голосов
/ 27 февраля 2020

Нет никаких оснований ожидать результата от 01 марта 2021 года. Действительно, тогда некоторые задались бы вопросом, почему добавление года к двум датам 29 февраля / 2020 и 01 марта 2020 года приведет к одинаковому результату 01 марта 2021 года для них обоих

1002 * Вместо Java следует четкому, непротиворечивому и простому правилу: если результат арифметики даты c (например, добавление месяцев или лет) приведет к неверной дате, то возвращенный ответ будет последним днем ​​месяца этого результата.

Например, с: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#plusMonths -длин-

  1. Добавить входные месяцы в поле месяца года
  2. Проверьте, если итоговая дата будет недействительной
  3. При необходимости настройте день месяца на последний действительный день

Например, 2007-03-31 плюс один месяц приведет к недействительности дата 2007-04-31. Вместо того, чтобы возвращать неверный результат, вместо него выбирается последний действительный день месяца, 2007-04-30.

1 голос
/ 27 февраля 2020

Использование:

System.out.println(dateAdd(new SimpleDateFormat("dd/MM/yyyy").parse("28/02/2020"),Calendar.DAY_OF_YEAR,366));
System.out.println(dateAdd(new SimpleDateFormat("dd/MM/yyyy").parse("29/02/2020"),Calendar.DAY_OF_YEAR,366));
0 голосов
/ 27 февраля 2020

Вы можете добавить год, а затем добавить день:

Date d = dateAdd(new SimpleDateFormat("dd/MM/yyyy").parse("28/02/2020"),Calendar.YEAR,1); // add a year
System.out.println(d);
d = dateAdd(d, Calendar.DATE, 1); // add a day
System.out.println(d);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...